package org.autoplot.jythonsupport.ui; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.SwingUtilities; import org.das2.datum.DatumRange; import org.das2.util.LoggerManager; import org.jdesktop.beansbinding.AutoBinding; import org.jdesktop.beansbinding.AutoBinding.UpdateStrategy; import org.jdesktop.beansbinding.BeanProperty; import org.jdesktop.beansbinding.Bindings; import org.autoplot.datasource.DataSetSelector; import org.autoplot.datasource.DataSetURI; import org.autoplot.datasource.DataSourceEditorPanel; import org.autoplot.datasource.DataSourceEditorPanelUtil; import org.autoplot.datasource.DataSourceUtil; import org.autoplot.datasource.URISplit; import org.autoplot.datasource.WindowManager; import org.das2.qds.filters.FiltersChainPanel; /** * GUI for creating a list of URIs and variables associated with them. * @author jbf */ public class NamedURIListTool extends JPanel { private static final Logger logger= LoggerManager.getLogger("jython.mashup"); private static final String CLASS_NAME = NamedURIListTool.class.getName(); protected static final String PROP_URIS= "uris"; /** * see code use, use is not typical. */ protected static final String PROP_ID="id"; JScrollPane scrollPane; /** * list of URIs. */ List uris=null; /** * list of Java identifiers, one for each URI. */ List ids=null; List isAuto= null; DataMashUp dataMashUp; public NamedURIListTool( ) { scrollPane = new javax.swing.JScrollPane(); ids= Collections.emptyList(); uris= Collections.emptyList(); isAuto= Collections.emptyList(); setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS)); add(scrollPane); refresh(); } /** * rebuild the GUI based on the uris. */ final public void refresh() { JPanel content= new JPanel(); BoxLayout lo= new BoxLayout( content, BoxLayout.Y_AXIS ); content.setLayout( lo ); for ( int i=0; i names ) { int max= 0; for (String n : names) { if ( n.startsWith("ds" ) ) { try { int j= Integer.parseInt(n.substring(2) ); max= Math.max(max,j); } catch ( NumberFormatException ex ) { } } } return "ds"+(max+1); } private void bindTimeRange( DataSetSelector dss ) { AutoBinding binding; binding = Bindings.createAutoBinding( UpdateStrategy.READ_WRITE, this, BeanProperty.create("timeRange"), dss, BeanProperty.create("timeRange")); binding.bind(); } private DatumRange timeRange; public static final String PROP_TIMERANGE = "timeRange"; public DatumRange getTimeRange() { return timeRange; } public void setTimeRange(DatumRange timeRange) { DatumRange oldTimeRange = this.timeRange; this.timeRange = timeRange; firePropertyChange(PROP_TIMERANGE, oldTimeRange, timeRange); } private boolean showIds = true; public static final String PROP_SHOWIDS = "showIds"; public boolean isShowIds() { return showIds; } public void setShowIds(boolean showIds) { boolean oldShowIds = this.showIds; this.showIds = showIds; firePropertyChange(PROP_SHOWIDS, oldShowIds, showIds); } /** * return the panel with the add and remove icons. * @param fi the position * @return one panel ( + panel GUI - ) */ private JPanel onePanel( final int fi ) { logger.entering( CLASS_NAME, "onePanel", fi ); final JPanel sub= new JPanel( new BorderLayout() ); sub.setName("sub"+fi); Dimension limit= new Dimension(100,24); if ( !showIds ) { limit= new Dimension(24,24); } Dimension dim= new Dimension(24,24); if ( fi>=0 ) { if ( showIds ) { JButton name= new JButton( ids.get(fi) + "=" ); name.setMaximumSize( limit ); name.setPreferredSize( limit ); name.setToolTipText( "press to rename " ); name.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { org.das2.util.LoggerManager.logGuiEvent(e); String oldName= ids.get(fi); renameAndEdit(fi); String newName= ids.get(fi); firePropertyChange( PROP_ID + "Name_"+fi, oldName, newName ); } } ); sub.add( name, BorderLayout.WEST ); } else { JButton subAdd= new JButton( new ImageIcon( FiltersChainPanel.class.getResource("/resources/add.png") ) ); subAdd.setMaximumSize( limit ); subAdd.setPreferredSize( limit ); subAdd.setToolTipText( "add new URI" ); subAdd.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { org.das2.util.LoggerManager.logGuiEvent(e); List ids= new ArrayList<>(NamedURIListTool.this.ids); List uris= new ArrayList<>(NamedURIListTool.this.uris); String newName= makeupName( ids ); ids.add(fi,newName); uris.add(fi,""); setIds(ids); setUris(uris); } } ); sub.add( subAdd, BorderLayout.WEST ); } } else { JButton subAdd= new JButton( new ImageIcon( FiltersChainPanel.class.getResource("/resources/add.png") ) ); subAdd.setMaximumSize( limit ); subAdd.setPreferredSize( limit ); subAdd.setToolTipText( "add new URI" ); subAdd.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { org.das2.util.LoggerManager.logGuiEvent(e); List ids= new ArrayList<>(NamedURIListTool.this.ids); List uris= new ArrayList<>(NamedURIListTool.this.uris); List isAuto= new ArrayList<>(NamedURIListTool.this.isAuto); String newName= makeupName( ids ); ids.add(newName); uris.add(""); isAuto.add(true); setIds(ids); setUris(uris); setIsAuto(isAuto); } } ); sub.add( subAdd, BorderLayout.WEST ); } if ( fi>=0 ) { JButton subDelete= new JButton( new ImageIcon( FiltersChainPanel.class.getResource("/resources/subtract.png") ) ); subDelete.setMaximumSize( limit ); subDelete.setPreferredSize( dim ); subDelete.setToolTipText( "remove uri " ); final int ffi= fi; subDelete.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { //TODO: delete URI Container parent= sub.getParent(); parent.remove(sub); parent.validate(); uris.remove(ffi); ids.remove(ffi); isAuto.remove(ffi); refresh(); } } ); JPanel p= new JPanel(); p.setLayout( new BoxLayout( p, BoxLayout.X_AXIS ) ); p.add( Box.createHorizontalStrut(11) ); p.add( subDelete ); sub.add( p, BorderLayout.EAST ); } if ( fi>=0 ) { final DataSetSelector dss= new DataSetSelector(); dss.setPlotItButtonVisible(false); dss.setPlayButton(false); dss.setValue( uris.get(fi) ); bindTimeRange(dss); try{ List recent= DataSetSelector.getDefaultRecent(); List recentSansInline= new ArrayList<>(); for ( String s: recent ) { if ( s.startsWith("vap+inline:") ) { if ( s.contains("getDataSet") ) { logger.log(Level.FINEST, "skipping {0}", s); continue; // don't include mash-ups in the list of things to mash-up. } } URISplit split= URISplit.parse(s); if ( ".jy".equals(split.ext) ) { logger.log(Level.FINEST, "skipping {0}", s); continue; } if ( !".vap".equals(split.ext) ) { recentSansInline.add(s); } } recentSansInline.addAll( uris ); LinkedHashSet nuris= new LinkedHashSet<>(); nuris.addAll( recentSansInline ); dss.setRecent( new ArrayList(nuris) ); //TODO: This was breaking mashup tool, clearing all entries. } catch ( IllegalArgumentException ex ) { } dss.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String newName= null; String currentName= null; if ( isAuto.get(fi) || uris.get(fi).trim().length()==0 ) { List nids= new ArrayList<>(ids); List nuris= new ArrayList<>(uris); nids.remove(fi); nuris.remove(fi); newName= DataSourceUtil.guessNameFor( dss.getValue(), nuris, nids ); if ( isValidIdentifier(newName) ) { currentName= ids.get( fi ); } } String uri= dss.getValue(); String uri2= DataSetURI.blurTsbUri(uri); uris.set( fi,uri2 ); if ( !uri.equals(uri2) ) { dss.setValue(uri2); } if (dataMashUp!=null ) dataMashUp.refresh(); if ( currentName!=null && newName!=null ) { doVariableRename( fi, currentName, newName ); } } }); dss.getEditor().addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { uris.set( fi,dss.getValue()); if (dataMashUp!=null ) dataMashUp.refresh(); } }) ; sub.add( dss, BorderLayout.CENTER ); } else { final JLabel tf= new JLabel(); tf.setText(" (click to add)"); sub.add( tf, BorderLayout.CENTER ); } Dimension maximumSize = sub.getPreferredSize(); maximumSize.width = Integer.MAX_VALUE; sub.setMaximumSize(maximumSize); return sub; } private void doVariableRename( int fi, String oldName, String newName ) { ids.set( fi, newName ); refresh(); if ( dataMashUp!=null ) dataMashUp.rename( oldName, newName ); } /** * returns true if the string is a valid Java (and Python) identifier. * @param n * @return */ private boolean isValidIdentifier( String n ) { boolean s= n.length()>0 && Character.isJavaIdentifierStart(n.charAt(0) ); for ( int i=1; s && i nids= new ArrayList(ids); List nuris= new ArrayList(uris); nids.remove(fi); nuris.remove(fi); newName= DataSourceUtil.guessNameFor(edit.getURI(),nuris,nids); } if ( isValidIdentifier(newName) ) { if ( !currentName.equals(newName) ) { doVariableRename( fi, currentName, newName ); } isAuto.set( fi, !cb.isSelected() ); if ( edit!=null ) { String uri= edit.getURI(); uri= DataSetURI.blurTsbUri(uri); uris.set( fi, uri ); } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { refresh(); } }); break; } } } public void setIds( List ids ) { this.ids= new ArrayList<>(ids); if ( uris.size()==ids.size() ) refresh(); } public void setUris( List uris ) { this.uris= new ArrayList<>(uris); if ( uris.size()==ids.size() ) refresh(); } public void setIsAuto( List isAuto ) { this.isAuto= new ArrayList<>(isAuto); if ( isAuto.size()==isAuto.size() ) refresh(); } /** * return the Jython code that gets these. * @return the Jython code that gets these. */ protected String getAsJython() { StringBuilder b= new StringBuilder(); for ( int i=0; i0 ) { String s= this.uris.get(i); if ( s.contains("'") ) { logger.info("removing single quotes from URI, hope that doesn't break anything."); b.append( this.ids.get(i) ).append( "=" ).append( "getDataSet('").append( s.replaceAll("'","") ).append("\')&"); } else { b.append( this.ids.get(i) ).append( "=" ).append( "getDataSet('").append( s ).append("')&"); } } } return b.toString(); } /** * return null if nothing is selected, the URI otherwise. * @param id the current selection, which can be an identifier, QDataSet.UNITS, or 10.0. * @return null if nothing is selected, the URI otherwise. */ public String selectDataId( String id ) { JPanel dsSelector1= new JPanel(); JPanel dsSelector= new JPanel(); dsSelector1.add( new JScrollPane( dsSelector, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ) ); dsSelector1.setPreferredSize( new Dimension(600,500 ) ); dsSelector1.setMaximumSize( new Dimension(600,500 ) ); dsSelector.setLayout( new BoxLayout(dsSelector,BoxLayout.Y_AXIS ) ); ButtonGroup bg= new ButtonGroup(); JCheckBox[] butts= new JCheckBox[this.uris.size()+2]; GridBagLayout layout= new GridBagLayout(); dsSelector.setLayout(layout); GridBagConstraints c= new GridBagConstraints(); c.anchor= GridBagConstraints.WEST; c.weighty= 0.0; int i; for ( i=0; i