From ede1e100824dea19a919f082f91a9697b391ce32 Mon Sep 17 00:00:00 2001 From: jprocter Date: Tue, 22 Jun 2010 12:37:22 +0000 Subject: [PATCH] prototype - implementation in progress JAL-591 --- src/jalview/gui/WsJobParameters.java | 887 +++++++++++++++++++++++++++++++ src/jalview/ws/jws2/Jws2Discoverer.java | 24 +- 2 files changed, 907 insertions(+), 4 deletions(-) create mode 100644 src/jalview/gui/WsJobParameters.java diff --git a/src/jalview/gui/WsJobParameters.java b/src/jalview/gui/WsJobParameters.java new file mode 100644 index 0000000..7c4391e --- /dev/null +++ b/src/jalview/gui/WsJobParameters.java @@ -0,0 +1,887 @@ +package jalview.gui; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.awt.event.WindowStateListener; +import java.util.ArrayList; +import java.util.EventObject; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextArea; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.border.TitledBorder; +import javax.swing.event.CellEditorListener; +import javax.swing.table.*; + +import compbio.metadata.Argument; +import compbio.metadata.Option; +import compbio.metadata.Parameter; +import compbio.metadata.Preset; +import compbio.metadata.PresetManager; +import compbio.metadata.RunnerConfig; +import compbio.metadata.ValueConstrain; +import compbio.metadata.ValueConstrain.Type; + +import jalview.ws.jws2.Jws2Discoverer; +import jalview.ws.jws2.Jws2Discoverer.Jws2Instance; + +public class WsJobParameters extends JPanel +{ + JPanel setDetails = new JPanel(); + + JPanel settingsPanel = new JPanel(); + + JPanel jobOptions = new JPanel(); + + JPanel jobParameters = new JPanel(); + + JPanel paramButtons = new JPanel(); + + JButton exportParams = new JButton(); + + JButton importParams = new JButton(); + + JButton resetParams = new JButton(); + + JButton addParam = new JButton(); + + JButton removeParam = new JButton(); + + JButton editParam = new JButton(); + + JLabel setName = new JLabel(); + + JTextArea setDescr = new JTextArea(); + + JTable paramTable = new JTable(); + + JScrollPane paramPane = new JScrollPane(); + + RunnerConfig serviceOptions; + + List availableParameters; + + private BorderLayout jparamLayout; + + WsJobParameters(Jws2Instance service) + { + this(service, null); + } + + public WsJobParameters(Jws2Instance service, Preset p) + { + this(null, service, p); + } + + /** + * + * @param desktop + * - if null, create new JFrame outside of desktop + * @param service + * @param p + */ + public WsJobParameters(JFrame parent, Jws2Instance service, Preset p) + { + super(); + jbInit(); + initTableUI(); + // populate parameter table + initForService(service, p); + // display in new JFrame attached to parent. + validate(); + } + + private void jbInit() + { + exportParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10)); + exportParams.setText("Export"); + exportParams.setToolTipText("Export parameters to a file"); + exportParams.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + exportParams_actionPerformed(e); + } + }); + importParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10)); + importParams.setText("Import"); + importParams.setToolTipText("Import parameters from a file"); + importParams.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + importParams_actionPerformed(e); + } + }); + resetParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10)); + resetParams.setText("Defaults"); + resetParams.setToolTipText("Reset to defaults"); + resetParams.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + resetParams_actionPerformed(e); + } + }); + addParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10)); + addParam.setText("Add"); + addParam.setToolTipText("Add new parameter"); + addParam.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + addParam_actionPerformed(e); + } + }); + removeParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10)); + removeParam.setText("Remove"); + removeParam.setToolTipText("Remove selected parameter"); + removeParam.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + removeParam_actionPerformed(e); + } + }); + editParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10)); + editParam.setText("Edit"); + editParam.setToolTipText("Edit selected parameter"); + editParam.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + editParam_actionPerformed(e); + } + }); + + setDetails.setBorder(new TitledBorder("Details")); + setDetails.setLayout(new GridLayout(2, 1)); + setDescr.setColumns(40); + setDescr.setWrapStyleWord(true); + setDescr.setPreferredSize(new Dimension(350, 100)); + setDetails.add(setName); + setDetails.add(setDescr); + setDetails.setPreferredSize(new Dimension(360, 150)); + settingsPanel.setLayout(new BorderLayout()); + jobOptions.setBorder(new TitledBorder("Options")); + jobParameters.setBorder(new TitledBorder("Parameters")); + jobParameters.setLayout(jparamLayout = new BorderLayout()); + paramPane.setPreferredSize(new Dimension(360, 300)); + paramButtons.setLayout(new GridLayout(2, 3)); + paramButtons.add(addParam); + paramButtons.add(editParam); + paramButtons.add(removeParam); + // TODO: relayout buttons nicely + paramButtons.add(exportParams); + paramButtons.add(importParams); + paramButtons.add(resetParams); + jobParameters.add(paramPane, BorderLayout.NORTH); + jobParameters.add(paramButtons, BorderLayout.SOUTH); + settingsPanel.add(jobOptions, BorderLayout.NORTH); + settingsPanel.add(jobParameters, BorderLayout.SOUTH); + setLayout(new BorderLayout()); + setPreferredSize(new Dimension(400, 600)); + setSize(new Dimension(400, 600)); + add(setDetails, BorderLayout.NORTH); + add(settingsPanel, BorderLayout.CENTER); + } + + /** + * need to populate table and validate after calling this to set up table and + * add it to pane + */ + public void initTableUI() + { + paramTable = new JTable(); + paramTable.getTableHeader() + .setFont(new Font("Verdana", Font.PLAIN, 12)); + paramTable.setFont(new Font("Verdana", Font.PLAIN, 12)); + + paramPane.getViewport().removeAll(); + paramPane.getViewport().add(paramTable); + paramTable.setDefaultRenderer(Argument.class, new ArgumentRenderer()); + paramTable.setDefaultRenderer(Parameter.class, new ArgumentRenderer()); + paramTable.setDefaultRenderer(Option.class, new ArgumentRenderer()); + paramTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + paramTable.addMouseListener(new MouseListener() + { + + @Override + public void mouseClicked(MouseEvent e) + { + if (e.getClickCount() > 1) + { + editParam_actionPerformed(null); + } + } + + @Override + public void mouseEntered(MouseEvent e) + { + // tooltips + // TODO Auto-generated method stub + + } + + @Override + public void mouseExited(MouseEvent e) + { + // tooltips + // TODO Auto-generated method stub + + } + + @Override + public void mousePressed(MouseEvent e) + { + // TODO Auto-generated method stub + + } + + @Override + public void mouseReleased(MouseEvent e) + { + // TODO Auto-generated method stub + + } + + }); + // paramTable.setDefaultEditor(Argument.class, new WsArgumentEditor(this)); + } + + public class WsArgumentEditor implements TableCellEditor + { + + int p; + + Argument arg; + + WsJobParameters wsparm; + + public WsArgumentEditor(WsJobParameters wsJobParameters) + { + wsparm = wsJobParameters; + p = wsparm.paramTable.getSelectedRow(); + arg = (Argument) wsparm.paramTable.getValueAt(p, wsparm.paramTable + .getSelectedColumn()); + /* + * if (arg instanceof Option) { if + * (JOptionPane.showInternalConfirmDialog(Desktop.desktop, + * "Remove option "+arg.getName(), + * "Delete option ?",JOptionPane.YES_NO_OPTION, + * JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { + * + * } } + */ + } + + @Override + public Component getTableCellEditorComponent(JTable table, + Object value, boolean isSelected, int row, int column) + { + // TODO Auto-generated method stub + return null; + } + + @Override + public void addCellEditorListener(CellEditorListener l) + { + // TODO Auto-generated method stub + + } + + @Override + public void cancelCellEditing() + { + // TODO Auto-generated method stub + + } + + @Override + public Object getCellEditorValue() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isCellEditable(EventObject anEvent) + { + // TODO Auto-generated method stub + return false; + } + + @Override + public void removeCellEditorListener(CellEditorListener l) + { + // TODO Auto-generated method stub + + } + + @Override + public boolean shouldSelectCell(EventObject anEvent) + { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean stopCellEditing() + { + // TODO Auto-generated method stub + return false; + } + + } + + protected void editParam_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + + protected void removeParam_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + + protected void addParam_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + + protected void resetParams_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + + protected void importParams_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + + protected void exportParams_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + + void initForService(Jws2Instance service, Preset p) + { + serviceOptions = service.getRunnerConfig(); + updateTable(p); + } + + @SuppressWarnings("unchecked") + private void updateTable(Preset p) + { + WsParameterTableModel mdl = null; + TableModel tmdl = paramTable.getModel(); + if (tmdl instanceof WsParameterTableModel) + { + mdl = (WsParameterTableModel) tmdl; + } + if (mdl == null) + { + paramTable.setModel(mdl = new WsParameterTableModel()); + } + availableParameters = new ArrayList(); + List setargs = new ArrayList(); + // populate table from default parameter set. + List args = serviceOptions.getArguments(); + + // split to params and required arguments + { + for (Argument arg : args) + { + Argument myarg = (Argument) arg; + // Ideally, Argument would implement isRequired ! + if (myarg instanceof Parameter) + { + Parameter parm = (Parameter) myarg; + if (parm.isRequired()) + { + setargs.add(parm); + } + else + { + availableParameters.add(parm); + } + } + else + { + if (myarg instanceof Option) + { + Option opt = (Option) myarg; + addOption(opt); + if (opt.isRequired()) + { + selectOption(opt, opt.getDefaultValue()); + } + } + else + { + System.err.println("Ignoring unknown service argument type " + + arg.getClass().getName()); + } + } + } + } + + if (p != null) + { + setDescr.setText(p.getDescription()); + setName.setText(p.getName()); + // TODO - URL link + try + { + args = p.getArguments(serviceOptions); + } catch (Exception e) + { + e.printStackTrace(); + } + setargs.clear(); + // get setargs from current object + if (args != null) + { + for (Argument arg : args) + { + if (arg instanceof Parameter) + { + setargs.add((Parameter) arg); + } + else + { + if (arg instanceof Option) + { + selectOption((Option) arg, arg.getDefaultValue()); + } + } + + } + } + } + + mdl.setData(setargs); + paramTable.setModel(mdl); + // paramTable.validate(); + jobOptions.setLayout(new GridLayout(optSet.size() / 2 + 1, 2)); + jobOptions.validate(); + } + + private void selectOption(Option opt, String string) + { + OptionBox cb = optSet.get(opt.getName()); + if (cb == null) + { + cb = addOption(opt); + } + if (string == null) + { + // no value specified. + if (opt.isRequired()) + { + // indicate option needs to be selected! + } + else + { + cb.enabled.setSelected(false); + } + } + else + { + cb.enabled.setSelected(true); + + if (opt.getPossibleValues().contains(string)) + { + cb.val.setSelectedItem(string); + } + else + { + throw new Error("Invalid value " + string + " for option " + opt); + } + + } + } + + Map optSet = new Hashtable(); + + public class OptionBox extends JPanel + { + JComboBox val = new JComboBox(); + + JCheckBox enabled = new JCheckBox(); + + public OptionBox(Option opt) + { + setLayout(new BorderLayout()); + enabled.setSelected(opt.isRequired()); + enabled.setFont(new Font("Verdana", Font.PLAIN, 11)); + enabled.setText(opt.getName()); + enabled.setToolTipText(opt.getDescription()); + add(enabled, BorderLayout.NORTH); + if (opt.getPossibleValues().size() > 1) + { + setLayout(new GridLayout(1,2)); + for (Object str : opt.getPossibleValues()) + { + val.addItem((String) str); + } + val.setSelectedItem((String) opt.getDefaultValue()); + add(val, BorderLayout.SOUTH); + } + // TODO: add actionListeners for popup (to open further info), + // and to update list of parameters if an option is enabled + // that takes a value. + } + } + + private OptionBox addOption(Option opt) + { + OptionBox cb = optSet.get(opt.getName()); + if (cb == null) + { + cb = new OptionBox(opt); + optSet.put(opt.getName(), cb); + jobOptions.add(cb); + } + return cb; + } + + class WsParameterTableModel extends AbstractTableModel + { + // arg list - vector for thread safety + public Vector data = new Vector(); + + private String[] colNames = + { "Parameter", "Value" }; + + @Override + public int getColumnCount() + { + return 2; + } + + @Override + public int findColumn(String columnName) + { + // TODO Auto-generated method stub + return super.findColumn(columnName); + } + + public void setData(List setargs) + { + if (setargs != null) + { + data = new Vector(setargs); + + } + else + { + data = new Vector(); + } + } + + public List getData() + { + return new ArrayList(data); + } + + @Override + public int getRowCount() + { + return data.size(); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) + { + if (rowIndex >= 0 && rowIndex < data.size()) + { + Parameter prm = data.elementAt(rowIndex); + switch (columnIndex) + { + case 0: + return prm.getName(); + case 1: + Object exc = null; + // the accessor name for the parameter value is possibly confusing + String val = prm.getDefaultValue(); + try + { + if (prm.getValidValue().getType().equals(Type.Float)) + { + exc = new Float(0); + return Float.parseFloat(val); + } + if (prm.getValidValue().getType().equals(Type.Integer)) + { + exc = new Integer(0); + return Integer.parseInt(val); + } + } catch (NumberFormatException e) + { + return exc; + } + // must be a string + return val; + + default: + } + } + return null; + } + + /* + * (non-Javadoc) + * + * @see javax.swing.table.AbstractTableModel#getColumnClass(int) + */ + @Override + public Class getColumnClass(int columnIndex) + { + switch (columnIndex) + { + case 0: + return String.class; + case 1: + return Parameter.class; + } + return super.getColumnClass(columnIndex); + } + + /* + * (non-Javadoc) + * + * @see javax.swing.table.AbstractTableModel#getColumnName(int) + */ + @Override + public String getColumnName(int column) + { + return colNames[column]; + } + + /* + * (non-Javadoc) + * + * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int) + */ + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) + { + if (columnIndex == 1) + { + return true; + } + return false; + } + } + + class ArgumentRenderer implements TableCellRenderer + { + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, int row, + int column) + { + if (value instanceof Option) + { + JCheckBox cb = new JCheckBox(); + cb.setSelected(true); + return cb; + } + if (value instanceof Boolean) + { + JCheckBox cb = new JCheckBox(); + cb.setSelected(((Boolean) value).booleanValue()); + return cb; + } + if (value instanceof String) + { + JLabel lbl = new JLabel(); + lbl.setFont(new Font("Verdana", Font.PLAIN, 11)); + lbl.setText((String) value); + return lbl; + } + if (value instanceof Parameter) + { + String val = ((Parameter) value).getDefaultValue(); + ValueConstrain constr = ((Parameter) value).getValidValue(); + JLabel lbl = new JLabel(); + lbl.setFont(new Font("Verdana", Font.PLAIN, 11)); + lbl.setText(val); + return lbl; + /* + * type dependent return value if + * (constr.getType().equals(Type.Integer)) + * + * { lbl.setText(val); } if (constr.getType().equals(Type.Float)) { } + * return lbl; + */ + } + return null; + } + } + + /** + * testing method - grab a service and parameter set and show the window + * + * @param args + */ + public static void main(String[] args) + { + jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer + .getDiscoverer(); + int p = 0; + if (args.length > 3) + { + Vector services = new Vector(); + services.addElement(args[p++]); + Jws2Discoverer.setServiceUrls(services); + } + try + { + disc.run(); + } catch (Exception e) + { + System.err.println("Aborting. Problem discovering services."); + e.printStackTrace(); + return; + } + Jws2Discoverer.Jws2Instance lastserv = null; + for (Jws2Discoverer.Jws2Instance service : disc.getServices()) + { + lastserv = service; + if (p < args.length && service.serviceType.equalsIgnoreCase(args[p])) + { + break; + } + } + if (lastserv != null) + { + Preset pr = null; + if (++p < args.length) + { + PresetManager prman = lastserv.getPresets(); + if (prman != null) + { + pr = prman.getPresetByName(args[p]); + if (pr == null) + { + // just grab the last preset. + List prl = prman.getPresets(); + pr = prl.get(prl.size() - 1); + } + } + } + while (true) + { + WsJobParameters pgui = new WsJobParameters(lastserv, pr); + JFrame jf = new JFrame("Parameters for " + lastserv.getActionText()); + JPanel cont = new JPanel(); + cont.setSize(new Dimension(600, 800)); + cont.add(pgui); + jf.add(cont); + final Thread thr = Thread.currentThread(); + jf.addWindowListener(new WindowListener() + { + + @Override + public void windowActivated(WindowEvent e) + { + // TODO Auto-generated method stub + + } + + @Override + public void windowClosed(WindowEvent e) + { + } + + @Override + public void windowClosing(WindowEvent e) + { + thr.interrupt(); + + } + + @Override + public void windowDeactivated(WindowEvent e) + { + // TODO Auto-generated method stub + + } + + @Override + public void windowDeiconified(WindowEvent e) + { + // TODO Auto-generated method stub + + } + + @Override + public void windowIconified(WindowEvent e) + { + // TODO Auto-generated method stub + + } + + @Override + public void windowOpened(WindowEvent e) + { + // TODO Auto-generated method stub + + } + + }); + jf.setVisible(true); + boolean inter = false; + while (!inter) + { + try + { + Thread.sleep(10000); + } catch (Exception e) + { + inter = true; + } + ; + } + jf.dispose(); + } + } + } +} diff --git a/src/jalview/ws/jws2/Jws2Discoverer.java b/src/jalview/ws/jws2/Jws2Discoverer.java index d982981..918abce 100644 --- a/src/jalview/ws/jws2/Jws2Discoverer.java +++ b/src/jalview/ws/jws2/Jws2Discoverer.java @@ -21,8 +21,10 @@ import jalview.datamodel.AlignmentView; import jalview.gui.AlignFrame; import jalview.ws.WSMenuEntryProviderI; import compbio.data.msa.MsaWS; +import compbio.metadata.Option; import compbio.metadata.Preset; import compbio.metadata.PresetManager; +import compbio.metadata.RunnerConfig; import compbio.ws.client.Jws2Base; import compbio.ws.client.Jws2Base.Services; @@ -160,11 +162,11 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI public class Jws2Instance { - String hosturl; + public String hosturl; - String serviceType; + public String serviceType; - MsaWS service; + public MsaWS service; public Jws2Instance(String hosturl, String serviceType, MsaWS service) { @@ -224,12 +226,21 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI return "Align with " + serviceType; } + + /** + * non-thread safe - blocks whilst accessing service to get complete set of available options and parameters + * @return + */ + public RunnerConfig getRunnerConfig() + { + return service.getRunnerOptions(); + } }; /** * holds list of services. */ - Vector services; + protected Vector services; /** * find or add a submenu with the given title in the given menu @@ -432,4 +443,9 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI return null; } + public Vector getServices() + { + return (services==null) ? new Vector(): new Vector(services); + } + } -- 1.7.10.2