/* * CompletionsDataSourceEditor.java * * Created on Nov 5, 2010, 2:17:46 PM */ package org.autoplot.datasource; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.logging.Logger; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import org.das2.util.LoggerManager; import org.das2.util.monitor.ProgressMonitor; /** * Generic Editor based on completions was first developed with * JunoWavesDataSource, now will be used instead of completions * when file icon is used. * @author jbf */ public class CompletionsDataSourceEditor extends javax.swing.JPanel implements DataSourceEditorPanel { private static final Logger logger= LoggerManager.getLogger("apdss"); /** * maximum length of vap+xxx: in URIs. */ private static final int MAX_VAP_PREFIX = 14; String suri; /** * true indicates that this type of URI does not have a file component. */ boolean suriNoFile= false; List opsCbs; List opsComboBoxes; JComboBox arg0Cbs=null; String arg0Extra=null; JTextField arg0ExtraTF=null; Control arg0ComboBox=null; private static interface Control { String getValue(); void setValue(String s); } private static Control getFromComboBox( JComboBox tcb ) { return new Control() { @Override public String getValue() { return (String)tcb.getSelectedItem(); }; @Override public void setValue( String s ) { tcb.setSelectedItem(s); } }; } /** Creates new form CompletionsDataSourceEditor */ public CompletionsDataSourceEditor() { initComponents(); jScrollPane1.getVerticalScrollBar().setUnitIncrement( getFont().getSize() ); } /** * return true if surl is not a file (like with vap+cdaweb:...); * @param surl1 * @return true if the URI is not a file. */ private boolean isNotFile( String surl1 ) { URISplit split= URISplit.parse(surl1); return split.file==null || split.file.equals("") || split.file.equals("file:///"); } /** * prepare the completion context object. * @param surl1 the uri. * @param carotPos the position of the carot. * @return the completion context object. */ private CompletionContext prepareContext( String surl1, int carotPos ) { CompletionContext cc = new CompletionContext(); int qpos = surl1.lastIndexOf('?', carotPos); if ( qpos==-1 && carotPos==surl1.length() ) { // note qpos will never equal -1 because of calling code. int icolon= surl1.indexOf(":"); if ( suriNoFile ) { surl1= surl1.substring(0,icolon)+":?"+surl1.substring(icolon+1); qpos= icolon+1; } else { surl1= surl1+"?"; qpos= surl1.length()-1; } carotPos= surl1.length(); } cc.surl = surl1; cc.surlpos = carotPos; //resourceUriCarotPos if ( qpos != -1 && qpos < carotPos ) { // in query section int eqpos = surl1.lastIndexOf('=', carotPos - 1); int amppos = surl1.lastIndexOf('&', carotPos - 1); if (amppos == -1) { amppos = qpos; } if (eqpos > amppos) { cc.context = CompletionContext.CONTEXT_PARAMETER_VALUE; cc.completable = surl1.substring(eqpos + 1, carotPos); cc.completablepos = carotPos - (eqpos + 1); } else { cc.context = CompletionContext.CONTEXT_PARAMETER_NAME; cc.completable = surl1.substring(amppos + 1, carotPos); cc.completablepos = carotPos - (amppos + 1); //if (surl1.length() > carotPos && surl1.charAt(carotPos) != '&') { // insert implicit "&" // surl1 = surl1.substring(0, carotPos) + '&' + surl1.substring(carotPos); //} } } else { //throw new IllegalArgumentException("we aren't in the query section"); } return cc; } private List getCompletions( DataSourceFactory factory, String surl1, CompletionContext cc, ProgressMonitor mon ) throws URISyntaxException, Exception { URISplit split = URISplit.parse(surl1); List result; if (cc.context == CompletionContext.CONTEXT_PARAMETER_NAME) { String resourceUri= CompletionContext.get(CompletionContext.CONTEXT_FILE, cc); if ( resourceUri!=null ) { URI uri = DataSetURI.getURI( CompletionContext.get(CompletionContext.CONTEXT_FILE, cc) ); cc.resourceURI= DataSetURI.getResourceURI(uri); } cc.params = split.params; result = factory.getCompletions(cc, mon ); } else if (cc.context == CompletionContext.CONTEXT_PARAMETER_VALUE) { if ( suriNoFile ) { cc.resourceURI= null; } else { URI uri; uri= DataSetURI.getURI(CompletionContext.get(CompletionContext.CONTEXT_FILE, cc)); cc.resourceURI= DataSetURI.getResourceURI(uri); } cc.params = split.params; if (factory == null) { throw new IllegalArgumentException("unable to find data source factory"); } result = factory.getCompletions(cc, mon); } else { throw new IllegalArgumentException("we aren't in the query section"); } return result; } private void populateFromCompletions( DataSourceFactory dsf, ProgressMonitor mon ) throws URISyntaxException, Exception { int i= suri.indexOf("?"); if ( i==-1 ) { int icolon= suri.indexOf(":"); if ( suriNoFile && icolon>-1 && icolon map= URISplit.parseParams(split.params); CompletionContext cc= prepareContext( suri, i ); List first= getCompletions( dsf, suri, cc, mon ); List arg0= new ArrayList(); for ( CompletionContext cc1: first ) { if ( cc1.implicitName!=null && cc1.implicitName.equals("arg_0") ) { arg0.add(cc1); } } first.removeAll(arg0); opsCbs= new ArrayList<>(); opsComboBoxes= new ArrayList<>(); boolean empty= true; if ( arg0.size()>0 ) { JPanel optPanel= new JPanel( new BorderLayout() ); empty= false; String val= map.get("arg_0"); if ( val!=null ) { int ib= val.indexOf("["); if ( ib>-1 && val.endsWith("]") ) { // vap+hdf5:file:///home/jbf/Linux/Download/gnc_B_July_16_2012.hdf5.mat?EFW_Uncomp_U[0] arg0Extra= val.substring(ib); } } int isel=-1; List arg0options= new ArrayList(); for ( int ii=0; ii0 ) { optPanel.add( BorderLayout.NORTH, new JLabel(s) ); } } if ( arg0.get(ii).label!=null ) { //if ( arg0.get(ii).completable.length()==0 ) { // arg0options.add( arg0.get(ii).label ); // "Select parameter to plot:" //} else { arg0options.add( arg0.get(ii).completable + ": " +arg0.get(ii).label ); //} } else { arg0options.add( arg0.get(ii).completable ); } if ( arg0.get(ii).completable.equals(val) ) { isel= ii; } } JComboBox jopts= new JComboBox( arg0options.toArray() ); optPanel.add( BorderLayout.CENTER, jopts ); if ( isel!=-1 ) { jopts.setSelectedIndex(isel); } arg0ComboBox= getFromComboBox(jopts); if ( arg0Extra!=null ) { arg0ExtraTF= new JTextField(12); arg0ExtraTF.setText(arg0Extra); arg0ExtraTF.setToolTipText( "subset specifier like [2:] or [-100:]"); optPanel.add( BorderLayout.EAST, arg0ExtraTF ); } arg0Cbs= jopts; optPanel.setMaximumSize( new Dimension(10000,16) ); optionsPanel.add( optPanel ); optionsPanel.add( Box.createVerticalStrut(8) ); } for ( CompletionContext cc1: first ) { String ss= CompletionContext.insert(cc, cc1); //TODO: make this look like the jython data source dialog! JPanel optPanel= new JPanel( new BorderLayout() ); final JCheckBox jcheckBox= new JCheckBox( cc1.label ); optPanel.add( BorderLayout.WEST, jcheckBox ); opsCbs.add(jcheckBox); empty= false; if ( cc1.doc!=null && cc1.doc.trim().length()>0 ) { optPanel.add( BorderLayout.NORTH, new JLabel( cc1.doc ) ); //jcheckBox.setToolTipText( cc1.doc ); } int pos= ss.indexOf(cc1.completable); if ( pos>-1 ) pos+=cc1.completable.length(); // carot immediately following "=" CompletionContext cc2= prepareContext( ss, pos>-1 ? pos : ss.length() ); if ( cc2.context!=null ) { List second= getCompletions( dsf, ss, cc2, mon ); List options= new ArrayList(); String key= cc1.completable; if ( key!=null ) { int ii= key.indexOf("="); if (ii>-1 ) key= key.substring(0,ii); } else { logger.warning("bad key in uri"); continue; } String val= map.get( key ); if ( val!=null ) { //jcheckBox.setSelected(true); } //String sel= null; int isel= -1; String deft=null; for ( int ii=0; ii { TimeRangeTool tt= new TimeRangeTool(); tt.setSelectedRange(tcb.getSelectedItem().toString()); int r= WindowManager.showConfirmDialog( this, tt, "Select Time Range", JOptionPane.OK_CANCEL_OPTION ); if ( r==JOptionPane.OK_OPTION) { tcb.setSelectedItem(tt.getSelectedRange()); } }); button.setToolTipText("Time Range Tool"); valuePanel.add( tcb ); button.setAlignmentX( JComponent.LEFT_ALIGNMENT ); valuePanel.add( button ); control= valuePanel; Control c= getFromComboBox( tcb ); opsComboBoxes.add( c ); } else { final JComboBox jopts= new JComboBox( options.toArray() ); jopts.setEditable(true); optPanel.add( BorderLayout.CENTER, jopts ); if ( isel!=-1 ) { jopts.setSelectedIndex(isel); jcheckBox.setSelected(true); } else { if ( deft!=null ) { jopts.setSelectedItem(deft); } } jcheckBox.addItemListener( new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { jopts.setEnabled( jcheckBox.isSelected()); } } ); jopts.setEnabled( jcheckBox.isSelected()); opsComboBoxes.add( getFromComboBox(jopts) ); optPanel.setMaximumSize( new Dimension(10000,16) ); control= optPanel; } optionsPanel.add( control ); optionsPanel.add( Box.createVerticalStrut(8) ); } else { opsComboBoxes.add( null ); } } if ( empty ) { String id= split.vapScheme==null ? ( "for " + split.ext ) : split.vapScheme; optionsPanel.add( new JLabel("Data source "+ id + " provides no completions, so presumably there are no options available.")); } optionsPanel.add( Box.createGlue() ); } @Override public JPanel getPanel() { return this; } @Override public void setURI(String uri) { this.suri= uri; this.suriNoFile=isNotFile(uri); URISplit split= URISplit.parse(suri); Map params= URISplit.parseParams( split.params ); for ( Entry e: params.entrySet() ) { String s= e.getKey(); String v= e.getValue(); for ( int i=0; i-1 && icolon-1 ) s= s.substring(0,i); base.append( s ); amp= true; } if ( arg0ExtraTF!=null ) { if ( arg0ExtraTF.getText().trim().length()>0 ) { base.append( arg0ExtraTF.getText().trim() ); } } for ( int i=0; i//GEN-BEGIN:initComponents private void initComponents() { jLabel1 = new javax.swing.JLabel(); jScrollPane1 = new javax.swing.JScrollPane(); optionsPanel = new javax.swing.JPanel(); jLabel1.setText("Autoplot has attempted to create a GUI editor based on the completions of the data source. "); jLabel1.setVerticalAlignment(javax.swing.SwingConstants.TOP); optionsPanel.setAlignmentY(0.0F); optionsPanel.setLayout(new javax.swing.BoxLayout(optionsPanel, javax.swing.BoxLayout.Y_AXIS)); jScrollPane1.setViewportView(optionsPanel); org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(jLabel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 585, Short.MAX_VALUE) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 585, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(layout.createSequentialGroup() .add(jLabel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(0, 377, Short.MAX_VALUE)) .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() .add(35, 35, 35) .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE))) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel jLabel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JPanel optionsPanel; // End of variables declaration//GEN-END:variables @Override public void markProblems(List problems) { } }