JAL-1645 Version-Rel Version 2.9 Year-Rel 2015 Licensing glob
[jalview.git] / src / jalview / appletgui / CutAndPasteTransfer.java
old mode 100755 (executable)
new mode 100644 (file)
index 86f55b8..c8bb972
-/*\r
- * Jalview - A Sequence Alignment Editor and Viewer\r
- * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
- */\r
-\r
-package jalview.appletgui;\r
-\r
-import java.awt.*;\r
-import java.awt.event.*;\r
-\r
-import jalview.datamodel.*;\r
-import jalview.io.*;\r
-\r
-public class CutAndPasteTransfer extends Panel implements ActionListener, MouseListener\r
-{\r
-  boolean pdbImport = false;\r
-  boolean treeImport = false;\r
-  Sequence seq;\r
-  AlignFrame alignFrame;\r
-\r
-  public CutAndPasteTransfer(boolean forImport, AlignFrame alignFrame)\r
-  {\r
-    try {\r
-        jbInit();\r
-    } catch (Exception e) {\r
-        e.printStackTrace();\r
-    }\r
-\r
-    this.alignFrame = alignFrame;\r
-\r
-    if (!forImport)\r
-    {\r
-\r
-      buttonPanel.setVisible(false);\r
-    }\r
-  }\r
-\r
-  public String getText()\r
-  {\r
-    return textarea.getText();\r
-  }\r
-\r
-  public void setText(String text)\r
-  {\r
-    textarea.setText(text);\r
-  }\r
-\r
-  public void setPDBImport(Sequence seq)\r
-  {\r
-    this.seq = seq;\r
-    pdbImport = true;\r
-  }\r
-\r
-  public void setTreeImport()\r
-  {\r
-    treeImport = true;\r
-    ok.setLabel("Accept");\r
-  }\r
-\r
-\r
-  public void actionPerformed(ActionEvent evt)\r
-  {\r
-    if(evt.getSource()==ok)\r
-      ok_actionPerformed();\r
-    else if(evt.getSource()==cancel)\r
-      cancel_actionPerformed();\r
-  }\r
-\r
-  protected void ok_actionPerformed()\r
-  {\r
-    String text = getText();\r
-    int length = text.length();\r
-    textarea.append("\n");\r
-    if(textarea.getText().length()==length)\r
-    {\r
-      String warning = "\n\n#################################################\n"\r
-          +"WARNING!! THIS IS THE MAXIMUM SIZE OF TEXTAREA!!\n"\r
-          +"\nCAN'T INPUT FULL ALIGNMENT"\r
-          +"\n\nYOU MUST DELETE THIS WARNING TO CONTINUE"\r
-          +"\n\nMAKE SURE LAST SEQUENCE PASTED IS COMPLETE"\r
-          +"\n#################################################\n";\r
-      textarea.setText(text.substring(0, text.length()-warning.length())\r
-          +warning);\r
-\r
-      textarea.setCaretPosition(text.length());\r
-    }\r
-\r
-    if(pdbImport)\r
-    {\r
-      new MCview.AppletPDBViewer(text, AppletFormatAdapter.PASTE,\r
-                                 seq,\r
-                                 alignFrame.getSeqcanvas());\r
-    }\r
-    else if(treeImport)\r
-    {\r
-      try{\r
-        jalview.io.NewickFile fin = new jalview.io.NewickFile(textarea.getText(),\r
-            "Paste");\r
-\r
-        fin.parse();\r
-        if(fin.getTree()!=null)\r
-          alignFrame.loadTree(fin, "Pasted tree file");\r
-\r
-      }\r
-      catch (Exception ex)\r
-      {\r
-        textarea.setText("Could not parse Newick file!\n" + ex);\r
-        return;\r
-      }\r
-    }\r
-    else if(alignFrame!=null)\r
-    {\r
-      SequenceI[] sequences = null;\r
-\r
-      String format = new IdentifyFile().Identify(text, AppletFormatAdapter.PASTE);\r
-      try{\r
-        sequences = new AppletFormatAdapter().readFile(text, AppletFormatAdapter.PASTE, format);\r
-      }catch(java.io.IOException ex)\r
-      {\r
-        ex.printStackTrace();\r
-      }\r
-      if (sequences != null)\r
-      {\r
-        AlignFrame af = new AlignFrame(new Alignment(sequences), alignFrame.viewport.applet,\r
-                                       "Cut & Paste input - " + format,\r
-                                       false);\r
-        af.statusBar.setText("Successfully pasted alignment file");\r
-      }\r
-    }\r
-\r
-   if(this.getParent() instanceof Frame)\r
-    ((Frame)this.getParent()).setVisible(false);\r
-   else\r
-     ((Dialog)this.getParent()).setVisible(false);\r
-  }\r
-\r
-  protected void cancel_actionPerformed()\r
-  {\r
-    textarea.setText("");\r
-    if(this.getParent() instanceof Frame)\r
-     ((Frame)this.getParent()).setVisible(false);\r
-    else\r
-     ((Dialog)this.getParent()).setVisible(false);\r
-  }\r
-\r
-  protected TextArea textarea = new TextArea();\r
-  Button ok = new Button();\r
-  Button cancel = new Button();\r
-  protected Panel buttonPanel = new Panel();\r
-  BorderLayout borderLayout1 = new BorderLayout();\r
-\r
-\r
-  private void jbInit() throws Exception {\r
-      textarea.setFont(new java.awt.Font("Monospaced", Font.PLAIN, 10));\r
-      textarea.setText("Paste your alignment file here");\r
-      textarea.addMouseListener(this);\r
-      this.setLayout(borderLayout1);\r
-      ok.setLabel("New Window");\r
-      ok.addActionListener(this);\r
-      cancel.setLabel("Close");\r
-      cancel.addActionListener(this);\r
-      this.add(buttonPanel, BorderLayout.SOUTH);\r
-      buttonPanel.add(ok, null);\r
-      buttonPanel.add(cancel, null);\r
-      this.add(textarea, java.awt.BorderLayout.CENTER);\r
-  }\r
-\r
-  public void mousePressed(MouseEvent evt) {\r
-      if (textarea.getText().startsWith("Paste your")) {\r
-          textarea.setText("");\r
-     }\r
-  }\r
-  public void mouseReleased(MouseEvent evt){}\r
-  public void mouseClicked(MouseEvent evt){}\r
-  public void mouseEntered(MouseEvent evt){}\r
-  public void mouseExited(MouseEvent evt){}\r
-}\r
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9)
+ * Copyright (C) 2015 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.
+ *  
+ * 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 <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.appletgui;
+
+import jalview.analysis.AlignmentUtils;
+import jalview.api.ComplexAlignFile;
+import jalview.bin.JalviewLite;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.SequenceI;
+import jalview.io.AnnotationFile;
+import jalview.io.AppletFormatAdapter;
+import jalview.io.FileParse;
+import jalview.io.IdentifyFile;
+import jalview.io.NewickFile;
+import jalview.io.TCoffeeScoreFile;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.TCoffeeColourScheme;
+import jalview.util.MessageManager;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Dialog;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+
+public class CutAndPasteTransfer extends Panel implements ActionListener,
+        MouseListener
+{
+  boolean pdbImport = false;
+
+  boolean treeImport = false;
+
+  boolean annotationImport = false;
+
+  SequenceI seq;
+
+  AlignFrame alignFrame;
+
+  FileParse source = null;
+
+  public CutAndPasteTransfer(boolean forImport, AlignFrame alignFrame)
+  {
+    try
+    {
+      jbInit();
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+    }
+
+    this.alignFrame = alignFrame;
+
+    if (!forImport)
+    {
+      buttonPanel.setVisible(false);
+    }
+  }
+
+  public String getText()
+  {
+    return textarea.getText();
+  }
+
+  public void setText(String text)
+  {
+    textarea.setText(text);
+  }
+
+  public void setPDBImport(SequenceI seq)
+  {
+    this.seq = seq;
+    accept.setLabel(MessageManager.getString("action.accept"));
+    addSequences.setVisible(false);
+    pdbImport = true;
+  }
+
+  public void setTreeImport()
+  {
+    treeImport = true;
+    accept.setLabel(MessageManager.getString("action.accept"));
+    addSequences.setVisible(false);
+  }
+
+  public void setAnnotationImport()
+  {
+    annotationImport = true;
+    accept.setLabel(MessageManager.getString("action.accept"));
+    addSequences.setVisible(false);
+  }
+
+  public void actionPerformed(ActionEvent evt)
+  {
+    if (evt.getSource() == accept)
+    {
+      ok(true);
+    }
+    else if (evt.getSource() == addSequences)
+    {
+      ok(false);
+    }
+    else if (evt.getSource() == cancel)
+    {
+      cancel();
+    }
+  }
+
+  protected void ok(boolean newWindow)
+  {
+    String text = getText();
+    int length = text.length();
+    textarea.append("\n");
+    if (textarea.getText().length() == length)
+    {
+      String warning = "\n\n#################################################\n"
+              + "WARNING!! THIS IS THE MAXIMUM SIZE OF TEXTAREA!!\n"
+              + "\nCAN'T INPUT FULL ALIGNMENT"
+              + "\n\nYOU MUST DELETE THIS WARNING TO CONTINUE"
+              + "\n\nMAKE SURE LAST SEQUENCE PASTED IS COMPLETE"
+              + "\n#################################################\n";
+      textarea.setText(text.substring(0, text.length() - warning.length())
+              + warning);
+
+      textarea.setCaretPosition(text.length());
+    }
+
+    if (pdbImport)
+    {
+      openPdbViewer(text);
+
+    }
+    else if (treeImport)
+    {
+      if (!loadTree())
+      {
+        return;
+      }
+    }
+    else if (annotationImport)
+    {
+      loadAnnotations();
+    }
+    else if (alignFrame != null)
+    {
+      loadAlignment(text, newWindow, alignFrame.getAlignViewport());
+    }
+
+    // TODO: dialog should indicate if data was parsed correctly or not - see
+    // JAL-1102
+    if (this.getParent() instanceof Frame)
+    {
+      ((Frame) this.getParent()).setVisible(false);
+    }
+    else
+    {
+      ((Dialog) this.getParent()).setVisible(false);
+    }
+  }
+
+  /**
+   * Parses text as Newick Tree format, and loads on to the alignment. Returns
+   * true if successful, else false.
+   */
+  protected boolean loadTree()
+  {
+    try
+    {
+      NewickFile fin = new NewickFile(textarea.getText(), "Paste");
+
+      fin.parse();
+      if (fin.getTree() != null)
+      {
+        alignFrame.loadTree(fin, "Pasted tree file");
+        return true;
+      }
+    } catch (Exception ex)
+    {
+      // TODO: JAL-1102 - should have a warning message in dialog, not simply
+      // overwrite the broken input data with the exception
+      textarea.setText(MessageManager.formatMessage(
+              "label.could_not_parse_newick_file",
+              new Object[] { ex.getMessage() }));
+      return false;
+    }
+    return false;
+  }
+
+  /**
+   * Parse text as an alignment file and add to the current or a new window.
+   * 
+   * @param text
+   * @param newWindow
+   */
+  protected void loadAlignment(String text, boolean newWindow,
+          AlignViewport viewport)
+  {
+    AlignmentI al = null;
+
+    String format = new IdentifyFile().Identify(text,
+            AppletFormatAdapter.PASTE);
+    AppletFormatAdapter afa = new AppletFormatAdapter(alignFrame.alignPanel);
+    try
+    {
+      al = afa.readFile(text, AppletFormatAdapter.PASTE, format);
+      source = afa.getAlignFile();
+    } catch (java.io.IOException ex)
+    {
+      ex.printStackTrace();
+    }
+
+    if (al != null)
+    {
+      al.setDataset(null); // set dataset on alignment/sequences
+
+      /*
+       * SplitFrame option dependent on applet parameter for now.
+       */
+      boolean allowSplitFrame = alignFrame.viewport.applet
+              .getDefaultParameter("enableSplitFrame", false);
+      if (allowSplitFrame && openSplitFrame(al, format))
+      {
+        return;
+      }
+      if (newWindow)
+      {
+        AlignFrame af;
+
+        if (source instanceof ComplexAlignFile)
+        {
+          ColumnSelection colSel = ((ComplexAlignFile) source)
+                  .getColumnSelection();
+          SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
+                  .getHiddenSequences();
+          boolean showSeqFeatures = ((ComplexAlignFile) source)
+                  .isShowSeqFeatures();
+          ColourSchemeI cs = ((ComplexAlignFile) source).getColourScheme();
+          af = new AlignFrame(al, hiddenSeqs, colSel,
+                  alignFrame.viewport.applet, "Cut & Paste input - "
+                          + format, false);
+          af.getAlignViewport().setShowSequenceFeatures(showSeqFeatures);
+          af.changeColour(cs);
+        }
+        else
+        {
+          af = new AlignFrame(al, alignFrame.viewport.applet,
+                  "Cut & Paste input - " + format, false);
+        }
+
+        af.statusBar
+                .setText(MessageManager
+                        .getString("label.successfully_pasted_annotation_to_alignment"));
+      }
+      else
+      {
+        alignFrame.addSequences(al.getSequencesArray());
+        alignFrame.statusBar.setText(MessageManager
+                .getString("label.successfully_pasted_alignment_file"));
+      }
+    }
+  }
+
+  /**
+   * Check whether the new alignment could be mapped to the current one as
+   * cDNA/protein, if so offer the option to open as split frame view. Returns
+   * true if a split frame view is opened, false if not.
+   * 
+   * @param al
+   * @return
+   */
+  protected boolean openSplitFrame(AlignmentI al, String format)
+  {
+    final AlignmentI thisAlignment = this.alignFrame.getAlignViewport()
+            .getAlignment();
+    if (thisAlignment.isNucleotide() == al.isNucleotide())
+    {
+      // both nucleotide or both protein
+      return false;
+    }
+    AlignmentI protein = thisAlignment.isNucleotide() ? al : thisAlignment;
+    AlignmentI dna = thisAlignment.isNucleotide() ? thisAlignment : al;
+    boolean mapped = AlignmentUtils.mapProteinToCdna(protein, dna);
+    if (!mapped)
+    {
+      return false;
+    }
+
+    /*
+     * A mapping is possible; ask user if they want a split frame.
+     */
+    String title = MessageManager.getString("label.open_split_window");
+    final JVDialog dialog = new JVDialog((Frame) this.getParent(), title,
+            true, 100, 400);
+    dialog.ok.setLabel(MessageManager.getString("action.yes"));
+    dialog.cancel.setLabel(MessageManager.getString("action.no"));
+    Panel question = new Panel(new BorderLayout());
+    final String text = MessageManager
+            .getString("label.open_split_window?");
+    question.add(new Label(text, Label.CENTER), BorderLayout.CENTER);
+    dialog.setMainPanel(question);
+    dialog.setVisible(true);
+    dialog.toFront();
+
+    if (!dialog.accept)
+    {
+      return false;
+    }
+
+    /*
+     * Open SplitFrame with DNA above and protein below, including the alignment
+     * from textbox and a copy of the original.
+     */
+    final JalviewLite applet = this.alignFrame.viewport.applet;
+    AlignFrame copyFrame = new AlignFrame(
+            this.alignFrame.viewport.getAlignment(), applet,
+            alignFrame.getTitle(), false, false);
+    AlignFrame newFrame = new AlignFrame(al, alignFrame.viewport.applet,
+            "Cut & Paste input - " + format, false, false);
+    AlignFrame dnaFrame = al.isNucleotide() ? newFrame : copyFrame;
+    AlignFrame proteinFrame = al.isNucleotide() ? copyFrame : newFrame;
+    SplitFrame sf = new SplitFrame(dnaFrame, proteinFrame);
+    sf.addToDisplay(false, applet);
+    return true;
+  }
+
+  /**
+   * Parse the text as a TCoffee score file, if successful add scores as
+   * alignment annotations.
+   */
+  protected void loadAnnotations()
+  {
+    TCoffeeScoreFile tcf = null;
+    try
+    {
+      tcf = new TCoffeeScoreFile(textarea.getText(),
+              jalview.io.AppletFormatAdapter.PASTE);
+      if (tcf.isValid())
+      {
+        if (tcf.annotateAlignment(alignFrame.viewport.getAlignment(), true))
+        {
+          alignFrame.tcoffeeColour.setEnabled(true);
+          alignFrame.alignPanel.fontChanged();
+          alignFrame.changeColour(new TCoffeeColourScheme(
+                  alignFrame.viewport.getAlignment()));
+          alignFrame.statusBar
+                  .setText(MessageManager
+                          .getString("label.successfully_pasted_tcoffee_scores_to_alignment"));
+        }
+        else
+        {
+          // file valid but didn't get added to alignment for some reason
+          alignFrame.statusBar.setText(MessageManager.formatMessage(
+                  "label.failed_add_tcoffee_scores",
+                  new Object[] { (tcf.getWarningMessage() != null ? tcf
+                          .getWarningMessage() : "") }));
+        }
+      }
+      else
+      {
+        tcf = null;
+      }
+    } catch (Exception x)
+    {
+      tcf = null;
+    }
+    if (tcf == null)
+    {
+      if (new AnnotationFile().annotateAlignmentView(alignFrame.viewport,
+              textarea.getText(), jalview.io.AppletFormatAdapter.PASTE))
+      {
+        alignFrame.alignPanel.fontChanged();
+        alignFrame.alignPanel.setScrollValues(0, 0);
+        alignFrame.statusBar
+                .setText(MessageManager
+                        .getString("label.successfully_pasted_annotation_to_alignment"));
+
+      }
+      else
+      {
+        if (!alignFrame.parseFeaturesFile(textarea.getText(),
+                jalview.io.AppletFormatAdapter.PASTE))
+        {
+          alignFrame.statusBar
+                  .setText(MessageManager
+                          .getString("label.couldnt_parse_pasted_text_as_valid_annotation_feature_GFF_tcoffee_file"));
+        }
+      }
+    }
+  }
+
+  /**
+   * Open a Jmol viewer (if available), failing that the built-in PDB viewer,
+   * passing the input text as the PDB file data.
+   * 
+   * @param text
+   */
+  protected void openPdbViewer(String text)
+  {
+    PDBEntry pdb = new PDBEntry();
+    pdb.setFile(text);
+
+    if (alignFrame.alignPanel.av.applet.jmolAvailable)
+    {
+      new jalview.appletgui.AppletJmol(pdb, new SequenceI[] { seq }, null,
+              alignFrame.alignPanel, AppletFormatAdapter.PASTE);
+    }
+    else
+    {
+      new MCview.AppletPDBViewer(pdb, new SequenceI[] { seq }, null,
+              alignFrame.alignPanel, AppletFormatAdapter.PASTE);
+    }
+  }
+
+  protected void cancel()
+  {
+    textarea.setText("");
+    if (this.getParent() instanceof Frame)
+    {
+      ((Frame) this.getParent()).setVisible(false);
+    }
+    else
+    {
+      ((Dialog) this.getParent()).setVisible(false);
+    }
+  }
+
+  protected TextArea textarea = new TextArea();
+
+  Button accept = new Button("New Window");
+
+  Button addSequences = new Button("Add to Current Alignment");
+
+  Button cancel = new Button("Close");
+
+  protected Panel buttonPanel = new Panel();
+
+  BorderLayout borderLayout1 = new BorderLayout();
+
+  private void jbInit() throws Exception
+  {
+    textarea.setFont(new java.awt.Font("Monospaced", Font.PLAIN, 10));
+    textarea.setText(MessageManager
+            .getString("label.paste_your_alignment_file"));
+    textarea.addMouseListener(this);
+    this.setLayout(borderLayout1);
+    accept.addActionListener(this);
+    addSequences.addActionListener(this);
+    cancel.addActionListener(this);
+    this.add(buttonPanel, BorderLayout.SOUTH);
+    buttonPanel.add(accept, null);
+    buttonPanel.add(addSequences);
+    buttonPanel.add(cancel, null);
+    this.add(textarea, java.awt.BorderLayout.CENTER);
+  }
+
+  public void mousePressed(MouseEvent evt)
+  {
+    if (textarea.getText().startsWith(
+            MessageManager.getString("label.paste_your")))
+    {
+      textarea.setText("");
+    }
+  }
+
+  public void mouseReleased(MouseEvent evt)
+  {
+  }
+
+  public void mouseClicked(MouseEvent evt)
+  {
+  }
+
+  public void mouseEntered(MouseEvent evt)
+  {
+  }
+
+  public void mouseExited(MouseEvent evt)
+  {
+  }
+}