X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FAppVarnaBinding.java;h=956c2e12726ac245adde2d7758aa7c7b8ad9590e;hb=792a03fc1994671ae23e7263cefd51c9b0da53cb;hp=105dd39ffa8a0b0ba75ec1cc787847cc0c81855e;hpb=722f0bee96b96ceeb8ef69b3ccd1aeff13786b2b;p=jalview.git diff --git a/src/jalview/gui/AppVarnaBinding.java b/src/jalview/gui/AppVarnaBinding.java index 105dd39..956c2e1 100644 --- a/src/jalview/gui/AppVarnaBinding.java +++ b/src/jalview/gui/AppVarnaBinding.java @@ -1,230 +1,639 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.6) - * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along with Jalview. If not, see . + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.gui; -import java.awt.Container; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetAdapter; +import java.awt.dnd.DropTargetDropEvent; import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.ContainerEvent; -import java.awt.event.ContainerListener; -import java.util.BitSet; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.swing.DefaultListModel; +import javax.swing.DefaultListSelectionModel; +import javax.swing.JLabel; +import javax.swing.JList; import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; -import jalview.api.AlignmentViewPanel; -import jalview.bin.Cache; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.SequenceI; -import jalview.structure.StructureSelectionManager; +import fr.orsay.lri.varna.VARNAPanel; +import fr.orsay.lri.varna.components.ReorderableJList; +import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed; +import fr.orsay.lri.varna.exceptions.ExceptionNAViewAlgorithm; +import fr.orsay.lri.varna.exceptions.ExceptionNonEqualLength; +import fr.orsay.lri.varna.models.FullBackup; +import fr.orsay.lri.varna.models.VARNAConfig; +import fr.orsay.lri.varna.models.rna.RNA; -import org.jmol.api.JmolAppConsoleInterface; -import org.jmol.api.JmolViewer; -import org.jmol.popup.JmolPopup; -import org.openscience.jmol.app.jmolpanel.AppConsole; +import jalview.datamodel.SequenceI; +import jalview.ext.varna.JalviewVarnaBinding; +import jalview.structure.AtomSpec; +import jalview.util.MessageManager; -public class AppVarnaBinding extends jalview.ext.jmol.JalviewJmolBinding +public class AppVarnaBinding extends JalviewVarnaBinding { + public VARNAPanel vp; + + // remove unused (commented out) fields? + // protected JPanel _tools = new JPanel(); + // + // private JPanel _input = new JPanel(); + // + // private JPanel _strPanel = new JPanel(); + // + // private JTextField _str = new JTextField(); + // + // private JTextField _seq = new JTextField(); + // + // private JLabel _strLabel = new JLabel( + // MessageManager.getString("label.str")); + // + // private JButton _updateButton = new JButton( + // MessageManager.getString("action.update")); + // + // private JButton _deleteButton = new JButton( + // MessageManager.getString("action.delete")); + // + // private JButton _duplicateButton = new JButton( + // MessageManager.getString("action.snapshot")); + // + protected JPanel _listPanel = new JPanel(); + + private ReorderableJList _sideList = null; + + private static String errorOpt = "error"; + + @SuppressWarnings("unused") + private boolean _error; + + private Color _backgroundColor = Color.white; + + private static int _nextID = 1; + + @SuppressWarnings("unused") + private int _algoCode; + + private BackupHolder _rnaList; /** - * + * Constructor */ - private AppJmol appJmolWindow; - - public AppVarnaBinding(AppJmol appJmol, StructureSelectionManager sSm, PDBEntry[] pdbentry, - SequenceI[][] sequenceIs, String[][] chains, String protocol) + public AppVarnaBinding() { - super(sSm, pdbentry, sequenceIs, chains, protocol); - appJmolWindow = appJmol; + init(); } - FeatureRenderer fr = null; - - @Override - public jalview.api.FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment) + /** + * Constructs the VARNAPanel and an (empty) selection list of structures to + * show in it + */ + private void init() { - AlignmentPanel ap = (alignment==null) ? appJmolWindow.ap : (AlignmentPanel) alignment; - if (ap.av.showSequenceFeatures) + DefaultListModel dlm = new DefaultListModel(); + + int marginTools = 40; + + DefaultListSelectionModel m = new DefaultListSelectionModel(); + m.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + m.setLeadAnchorNotificationEnabled(false); + + _sideList = new ReorderableJList(); + _sideList.setModel(dlm); + _sideList.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) { + AppVarnaBinding.this.mouseClicked(e); + } + }); + _sideList.setSelectionModel(m); + _sideList.setPreferredSize(new Dimension(100, 0)); + _sideList.addListSelectionListener(new ListSelectionListener() { - if (fr == null) + public void valueChanged(ListSelectionEvent evt) { - fr = new FeatureRenderer(ap); + changeSelectedStructure_actionPerformed(evt); } + }); + _rnaList = new BackupHolder(dlm, _sideList); - fr.transferSettings(ap. - seqPanel.seqCanvas.getFeatureRenderer()); + try + { + vp = new VARNAPanel("0", "."); + } catch (ExceptionNonEqualLength e) + { + vp.errorDialog(e); } + vp.setPreferredSize(new Dimension(400, 400)); + + JScrollPane listScroller = new JScrollPane(_sideList); + listScroller.setPreferredSize(new Dimension(150, 0)); + + vp.setBackground(_backgroundColor); + + // MC commented out stuff not added to panel - remove? + // Font textFieldsFont = Font.decode("MonoSpaced-PLAIN-12"); + // + // _seq.setFont(textFieldsFont); + // if (!rnaList.isEmpty()) + // { + // _seq.setText(rnaList.get(0).getSeq()); + // } + + // _updateButton.addActionListener(new ActionListener() + // { + // public void actionPerformed(ActionEvent e) + // { + // FullBackup sel = (FullBackup) _sideList.getSelectedValue(); + // sel.rna.setSequence("A"); + // } + // }); + // + // _strLabel.setPreferredSize(new Dimension(marginTools, 15)); + // _strLabel.setHorizontalTextPosition(JLabel.LEFT); + // _str.setFont(textFieldsFont); + // _strPanel.setLayout(new BorderLayout()); + // _strPanel.add(_strLabel, BorderLayout.WEST); + // _strPanel.add(_str, BorderLayout.CENTER); + // + // _input.setLayout(new GridLayout(1, 0)); + // _input.add(_strPanel); + // + // JPanel goPanel = new JPanel(); + // goPanel.setLayout(new BorderLayout()); + // + // _tools.setLayout(new BorderLayout()); + // _tools.add(_input, BorderLayout.CENTER); + // _tools.add(goPanel, BorderLayout.EAST); + // + // goPanel.add(_updateButton, BorderLayout.CENTER); + // + // JPanel ops = new JPanel(); + // ops.setLayout(new GridLayout(1, 2)); + // ops.add(_deleteButton); + // ops.add(_duplicateButton); + + JLabel j = new JLabel( + MessageManager.getString("label.structures_manager"), + JLabel.CENTER); + _listPanel.setLayout(new BorderLayout()); - return fr; + _listPanel.add(j, BorderLayout.NORTH); + _listPanel.add(listScroller, BorderLayout.CENTER); + + new DropTarget(vp, new DropTargetAdapter() { + @Override + public void drop(DropTargetDropEvent dtde) + { + AppVarnaBinding.this.drop(dtde); + } + }); } - @Override - public jalview.api.SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment) + public JPanel getListPanel() { - return new SequenceRenderer(((AlignmentPanel)alignment).av); + return _listPanel; } - public void sendConsoleEcho(String strEcho) + /** + * Returns the currently selected RNA, or null if none selected + * + * @return + */ + public RNA getSelectedRNA() { - if (console != null) + int selectedIndex = _sideList.getSelectedIndex(); + if (selectedIndex < 0) { - console.sendConsoleEcho(strEcho); + return null; } + FullBackup selected = _rnaList.getElementAt(selectedIndex); + return selected.rna; + } + + /** + * Substitute currently selected RNA with the edited one + * + * @param rnaEdit + */ + public void updateSelectedRNA(RNA rnaEdit) + { + vp.repaint(); + vp.showRNA(rnaEdit); } - public void sendConsoleMessage(String strStatus) + public static String generateDefaultName() { - if (console != null && strStatus != null) - // && !strStatus.equals("Script completed")) - // should we squash the script completed string ? + return "User file #" + _nextID++; + } + + public String[][] getParameterInfo() + { + String[][] info = { - console.sendConsoleMessage(strStatus); + // Parameter Name Kind of Value Description, + { "sequenceDBN", "String", "A raw RNA sequence" }, + { "structureDBN", "String", + "An RNA structure in dot bracket notation (DBN)" }, + { errorOpt, "boolean", "To show errors" }, }; + return info; + } + + @SuppressWarnings("unused") + private Color getSafeColor(String col, Color def) + { + Color result; + try + { + result = Color.decode(col); + } catch (Exception e) + { + try + { + result = Color.getColor(col, def); + } catch (Exception e2) + { + return def; + } } + return result; } - @Override - public void showUrl(String url, String target) + public VARNAPanel get_varnaPanel() + { + return vp; + } + + public void set_varnaPanel(VARNAPanel surface) + { + vp = surface; + } + + public void drop(DropTargetDropEvent dtde) { try { - jalview.util.BrowserLauncher.openURL(url); + Transferable tr = dtde.getTransferable(); + DataFlavor[] flavors = tr.getTransferDataFlavors(); + for (int i = 0; i < flavors.length; i++) + { + if (flavors[i].isFlavorJavaFileListType()) + { + dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); + Object ob = tr.getTransferData(flavors[i]); + if (ob instanceof List) + { + List list = (List) ob; + for (int j = 0; j < list.size(); j++) + { + Object o = list.get(j); + + if (dtde.getSource() instanceof DropTarget) + { + DropTarget dt = (DropTarget) dtde.getSource(); + Component c = dt.getComponent(); + if (c instanceof VARNAPanel) + { + String path = o.toString(); + VARNAPanel varnaPanel = (VARNAPanel) c; + try + { + FullBackup bck = VARNAPanel.importSession(path); + _rnaList.add(bck.config, bck.rna, bck.name, true); + } catch (ExceptionLoadingFailed e3) + { + int mn = 1; + Collection mdls = fr.orsay.lri.varna.factories.RNAFactory + .loadSecStr(path); + for (RNA r : mdls) + { + r.drawRNA(varnaPanel.getConfig()); + String name = r.getName(); + if (name.equals("")) + { + name = path.substring(path + .lastIndexOf(File.separatorChar) + 1); + } + if (mdls.size() > 1) + { + name += " (Model " + mn++ + ")"; + } + _rnaList.add(varnaPanel.getConfig().clone(), r, name, true); + } + } + } + } + } + } + // If we made it this far, everything worked. + dtde.dropComplete(true); + return; + } + } + // Hmm, the user must not have dropped a file list + dtde.rejectDrop(); } catch (Exception e) { - Cache.log.error("Failed to launch Jmol-associated url " + url, e); - // TODO: 2.6 : warn user if browser was not configured. + e.printStackTrace(); + dtde.rejectDrop(); } + } - @Override - public void refreshGUI() + private class BackupHolder { - // appJmolWindow.repaint(); - javax.swing.SwingUtilities.invokeLater(new Runnable() + private DefaultListModel _rnalist; + + private List _rnas = new ArrayList(); + + JList _l; + + public BackupHolder(DefaultListModel rnaList, JList l) + { + _rnalist = rnaList; + _l = l; + } + + public void add(VARNAConfig c, RNA r, String name) + { + add(c, r, name, false); + } + + /** + * Adds an entry to the end of the selection list and (optionally) sets it + * as selected + * + * @param c + * @param r + * @param name + * @param select + */ + public void add(VARNAConfig c, RNA r, String name, boolean select) { - public void run() + if (select) { - appJmolWindow.updateTitleAndMenus(); - appJmolWindow.revalidate(); + _l.removeSelectionInterval(0, _rnalist.size()); } - }); + if (name.equals("")) + { + name = generateDefaultName(); + } + FullBackup bck = new FullBackup(c, r, name); + _rnas.add(r); + _rnalist.addElement(bck); + if (select) + { + _l.setSelectedIndex(0); + } + } + + public FullBackup getElementAt(int i) + { + return _rnalist.getElementAt(i); + } } - public void updateColours(Object source) + public void mouseClicked(MouseEvent e) { - AlignmentPanel ap = (AlignmentPanel) source,topap; - // ignore events from unrelated or non-user interactive frames - if ((topap=appJmolWindow.getAlignmentPanelFor(ap.av.getAlignment()))==null || topap.alignFrame.getCurrentView() != ap.av || !appJmolWindow.isUsedforcolourby(ap)) - return; - if (!isLoadingFromArchive()) { - colourBySequence(ap.av.getShowSequenceFeatures(), ap); + if (e.getClickCount() == 2) + { + int index = _sideList.locationToIndex(e.getPoint()); + ListModel dlm = _sideList.getModel(); + // FullBackup item = dlm.getElementAt(index); + + _sideList.ensureIndexIsVisible(index); + /* + * TODO Object newName = JOptionPane.showInputDialog( this, + * "Specify a new name for this RNA", "Rename RNA", + * JOptionPane.QUESTION_MESSAGE, (Icon)null, null, item.toString()); if + * (newName!=null) { item.name = newName.toString(); + * this._sideList.repaint(); } + */ } } - public void notifyScriptTermination(String strStatus, int msWalltime) + @Override + public String[] getPdbFile() { - // todo - script termination doesn't happen ? - // if (console != null) - // console.notifyScriptTermination(strStatus, - // msWalltime); + return null; } - public void showUrl(String url) + @Override + public void releaseReferences(Object svl) { - showUrl(url, "jmol"); } - public void newJmolPopup(boolean translateLocale, String menuName, - boolean asPopup) + @Override + public void updateColours(Object source) { + } - jmolpopup = JmolPopup.newJmolPopup(viewer, translateLocale, menuName, - asPopup); + @Override + public void componentHidden(ComponentEvent e) + { } - public void selectionChanged(BitSet arg0) + @Override + public void componentMoved(ComponentEvent e) { - // TODO Auto-generated method stub + } + @Override + public void componentResized(ComponentEvent e) + { } - public void refreshPdbEntries() + @Override + public void componentShown(ComponentEvent e) { - // TODO Auto-generated method stub + } + @Override + public void highlightAtoms(List atoms) + { } - public void showConsole(boolean b) + @Override + public boolean isListeningFor(SequenceI seq) { - appJmolWindow.showConsole(b); + return true; } /** - * add the given sequences to the mapping scope for the given pdb file handle + * Returns the path to a temporary file containing a representation of the + * state of the Varna display, or null on any error + * + * @param rna + * @param jds * - * @param pdbFile - * - pdbFile identifier - * @param seq - * - set of sequences it can be mapped to + * @return */ - public void addSequenceForStructFile(String pdbFile, SequenceI[] seq) + public String getStateInfo(RNA rna) { - for (int pe = 0; pe < pdbentry.length; pe++) + if (vp == null) { - if (pdbentry[pe].getFile().equals(pdbFile)) + return null; + } + + /* + * we have to show the RNA we want to save in the viewer; get the currently + * displayed model first so we can restore it + */ + FullBackup sel = (FullBackup) _sideList.getSelectedValue(); + + FullBackup model = null; + ListModel models = _sideList.getModel(); + for (int i = 0; i < models.getSize(); i++) + { + model = (FullBackup) models.getElementAt(i); + if (model.rna == rna) { - addSequence(pe, seq); + break; } } + if (model == null) + { + return null; + } + + /* + * switch display + */ + vp.showRNA(model.rna, model.config); + + try + { + File temp; + temp = File.createTempFile("varna", null); + temp.deleteOnExit(); + String filePath = temp.getAbsolutePath(); + vp.toXML(filePath); + + /* + * restore the previous display + */ + vp.showRNA(sel.rna, sel.config); + + return filePath; + } catch (IOException e) + { + return null; + } } - @Override - protected JmolAppConsoleInterface createJmolConsole(JmolViewer viewer2, - Container consolePanel, String buttonsToShow) + public int getSelectedIndex() { - return new AppConsole(viewer, consolePanel, buttonsToShow); + return _sideList.getSelectedIndex(); } - @Override - protected void releaseUIResources() + /** + * Switch the Varna display to the structure selected in the left hand panel + * + * @param evt + */ + protected void changeSelectedStructure_actionPerformed(ListSelectionEvent evt) { - appJmolWindow = null; - if (console != null) + if (!evt.getValueIsAdjusting()) { - try - { - console.setVisible(false); - } catch (Error e) - { - } catch (Exception x) - { - } - ; - console = null; + showSelectedStructure(); } + } + /** + * + */ + protected void showSelectedStructure() + { + FullBackup sel = (FullBackup) _sideList.getSelectedValue(); + if (sel != null) + { + vp.showRNA(sel.rna, sel.config); + } } - @Override - public void releaseReferences(Object svl) + /** + * Set and display the selected item in the list of structures + * + * @param selectedRna + */ + public void setSelectedIndex(final int selectedRna) { - if (svl instanceof SeqPanel) { - appJmolWindow.removeAlignmentPanel(((SeqPanel) svl).ap); - - }; + /* + * note this does nothing if, say, selecting item 3 when only 1 has been + * added on load + */ + _sideList.setSelectedIndex(selectedRna); + // TODO ? need a worker thread to get this to happen properly + } + + /** + * Add an RNA structure to the selection list + * + * @param rna + */ + public void addStructure(RNA rna) + { + VARNAConfig config = vp.getConfig().clone(); + addStructure(rna, config); + } + + /** + * @param rna + * @param config + */ + protected void addStructure(final RNA rna, final VARNAConfig config) + { + drawRna(rna, config); + _rnaList.add(config, rna, rna.getName()); + } + + /** + * @param rna + * @param config + */ + protected void drawRna(final RNA rna, final VARNAConfig config) + { + try + { + rna.drawRNA(rna.getDrawMode(), config); + } catch (ExceptionNAViewAlgorithm e) + { + // only throwable for draw mode = 3 NAView + System.err.println("Error drawing RNA: " + e.getMessage()); + } } }