Merge branch 'features/JAL-1541_BioJsMSA' into develop
[jalview.git] / src / jalview / gui / AlignFrame.java
index bb8eec3..001c2d5 100644 (file)
  */
 package jalview.gui;
 
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.GridLayout;
-import java.awt.Rectangle;
-import java.awt.Toolkit;
-import java.awt.datatransfer.Clipboard;
-import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.StringSelection;
-import java.awt.datatransfer.Transferable;
-import java.awt.dnd.DnDConstants;
-import java.awt.dnd.DropTargetDragEvent;
-import java.awt.dnd.DropTargetDropEvent;
-import java.awt.dnd.DropTargetEvent;
-import java.awt.dnd.DropTargetListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.awt.print.PageFormat;
-import java.awt.print.PrinterJob;
-import java.beans.PropertyChangeEvent;
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Deque;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Set;
-import java.util.Vector;
-
-import javax.swing.JButton;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JEditorPane;
-import javax.swing.JInternalFrame;
-import javax.swing.JLabel;
-import javax.swing.JLayeredPane;
-import javax.swing.JMenu;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JProgressBar;
-import javax.swing.JRadioButtonMenuItem;
-import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
-
 import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentSorter;
 import jalview.analysis.AlignmentUtils;
@@ -140,6 +89,7 @@ import jalview.schemes.TaylorColourScheme;
 import jalview.schemes.TurnColourScheme;
 import jalview.schemes.UserColourScheme;
 import jalview.schemes.ZappoColourScheme;
+import jalview.structure.StructureSelectionManager;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.jws1.Discoverer;
@@ -147,6 +97,57 @@ import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.GridLayout;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DropTargetDragEvent;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetEvent;
+import java.awt.dnd.DropTargetListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.print.PageFormat;
+import java.awt.print.PrinterJob;
+import java.beans.PropertyChangeEvent;
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JEditorPane;
+import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
+import javax.swing.JLayeredPane;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+
 /**
  * DOCUMENT ME!
  * 
@@ -363,7 +364,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     final List<AlignmentPanel> selviews = new ArrayList<AlignmentPanel>();
     final List<AlignmentPanel> origview = new ArrayList<AlignmentPanel>();
-    ViewSelectionMenu vsel = new ViewSelectionMenu("Transfer colours from",
+    final String menuLabel = MessageManager
+            .getString("label.copy_format_from");
+    ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
             new ViewSetProvider()
             {
 
@@ -372,7 +375,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               {
                 origview.clear();
                 origview.add(alignPanel);
-                return Desktop.getAlignmentPanels(null);
+                // make an array of all alignment panels except for this one
+                List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>(
+                        Arrays.asList(Desktop.getAlignmentPanels(null)));
+                aps.remove(AlignFrame.this.alignPanel);
+                return aps.toArray(new AlignmentPanel[aps.size()]);
               }
             }, selviews, new ItemListener()
             {
@@ -382,32 +389,43 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               {
                 if (origview.size() > 0)
                 {
+                  final AlignmentPanel ap = origview.get(0);
+
+                  /*
+                   * Copy the ViewStyle of the selected panel to 'this one'.
+                   * Don't change value of 'scaleProteinAsCdna' unless copying
+                   * from a SplitFrame.
+                   */
                   ViewStyleI vs = selviews.get(0).getAlignViewport()
                           .getViewStyle();
-                  origview.get(0).getAlignViewport().setViewStyle(vs);
-                  AlignViewportI complement = origview.get(0)
-                          .getAlignViewport().getCodingComplement();
-                  if (complement != null)
+                  boolean fromSplitFrame = selviews.get(0)
+                          .getAlignViewport().getCodingComplement() != null;
+                  if (!fromSplitFrame)
+                  {
+                    vs.setScaleProteinAsCdna(ap.getAlignViewport()
+                            .getViewStyle().isScaleProteinAsCdna());
+                  }
+                  ap.getAlignViewport().setViewStyle(vs);
+
+                  /*
+                   * Also rescale ViewStyle of SplitFrame complement if there is
+                   * one _and_ it is set to 'scaledProteinAsCdna'; we don't copy
+                   * the whole ViewStyle (allow cDNA protein to have different
+                   * fonts)
+                   */
+                  AlignViewportI complement = ap.getAlignViewport()
+                          .getCodingComplement();
+                  if (complement != null && vs.isScaleProteinAsCdna())
                   {
                     AlignFrame af = Desktop.getAlignFrameFor(complement);
-                    if (complement.isNucleotide())
-                    {
-                      complement.setViewStyle(vs);
-                      vs.setCharWidth(vs.getCharWidth() / 3);
-                    }
-                    else
-                    {
-                      int rw = vs.getCharWidth();
-                      vs.setCharWidth(rw * 3);
-                      complement.setViewStyle(vs);
-                      vs.setCharWidth(rw);
-                    }
-                    af.alignPanel.updateLayout();
+                    ((SplitFrame) af.getSplitViewContainer())
+                            .adjustLayout();
                     af.setMenusForViewport();
                   }
-                  origview.get(0).updateLayout();
-                  origview.get(0).setSelected(true);
-                  origview.get(0).alignFrame.setMenusForViewport();
+
+                  ap.updateLayout();
+                  ap.setSelected(true);
+                  ap.alignFrame.setMenusForViewport();
 
                 }
               }
@@ -1194,7 +1212,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           omitHidden = viewport.getViewAsString(false);
         }
       }
-      FormatAdapter f = new FormatAdapter();
+      FeatureRenderer fr = new FeatureRenderer(this.alignPanel);
+      viewport.setFeatureRenderer(fr);
+      FormatAdapter f = new FormatAdapter(viewport);
       String output = f.formatSequences(format,
               viewport.getAlignment(), // class cast exceptions will
               // occur in the distant future
@@ -1264,7 +1284,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void outputText_actionPerformed(ActionEvent e)
   {
     String[] omitHidden = null;
-
+    FeatureRenderer fr = new FeatureRenderer(this.alignPanel);
+    viewport.setFeatureRenderer(fr);
     if (viewport.hasHiddenColumns())
     {
       int reply = JOptionPane
@@ -1288,7 +1309,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     try
     {
-      cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
+      cap.setText(new FormatAdapter(viewport).formatSequences(
+              e.getActionCommand(),
               viewport.getAlignment(), omitHidden,
               viewport.getColumnSelection()));
       Desktop.addInternalFrame(cap, MessageManager.formatMessage(
@@ -4781,8 +4803,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               sprods[s].updatePDBIds();
             }
             Alignment al = new Alignment(sprods);
-            Set<AlignedCodonFrame> cf = prods.getCodonFrames();
             al.setDataset(ds);
+
+            /*
+             * Copy dna-to-protein mappings to new alignment
+             */
+            // TODO 1: no mappings are set up for EMBL product
+            // TODO 2: if they were, should add them to protein alignment, not
+            // dna
+            Set<AlignedCodonFrame> cf = prods.getCodonFrames();
             for (AlignedCodonFrame acf : cf)
             {
               al.addCodonFrame(acf);
@@ -4794,12 +4823,33 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                     + getTitle();
             naf.setTitle(newtitle);
 
-            // remove this flag once confirmed we want a split view
-            boolean asSplitFrame = true;
+            // temporary flag until SplitFrame is released
+            boolean asSplitFrame = Cache.getDefault(
+                    Preferences.ENABLE_SPLIT_FRAME, false);
             if (asSplitFrame)
             {
-              final Alignment copyAlignment = new Alignment(new Alignment(
-                      AlignFrame.this.viewport.getSequenceSelection()));
+              /*
+               * Make a copy of this alignment (sharing the same dataset
+               * sequences). If we are DNA, drop introns and update mappings
+               */
+              AlignmentI copyAlignment = null;
+              final SequenceI[] sequenceSelection = AlignFrame.this.viewport
+                      .getSequenceSelection();
+              if (dna)
+              {
+                copyAlignment = AlignmentUtils.makeExonAlignment(
+                        sequenceSelection, cf);
+                al.getCodonFrames().clear();
+                al.getCodonFrames().addAll(cf);
+                final StructureSelectionManager ssm = StructureSelectionManager
+                        .getStructureSelectionManager(Desktop.instance);
+                ssm.addMappings(cf);
+              }
+              else
+              {
+                copyAlignment = new Alignment(new Alignment(
+                        sequenceSelection));
+              }
               AlignFrame copyThis = new AlignFrame(copyAlignment,
                       AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
               copyThis.setTitle(AlignFrame.this.getTitle());
@@ -4907,9 +4957,17 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               "label.translation_of_params", new Object[]
               { this.getTitle() });
       af.setTitle(newTitle);
-      final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
-      viewport.openSplitFrame(af, new Alignment(seqs), al.getCodonFrames());
-      // Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+      if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, false))
+      {
+        final SequenceI[] seqs = viewport.getSelectionAsNewSequence();
+        viewport.openSplitFrame(af, new Alignment(seqs),
+                al.getCodonFrames());
+      }
+      else
+      {
+        Desktop.addInternalFrame(af, newTitle, DEFAULT_WIDTH,
+                DEFAULT_HEIGHT);
+      }
     }
   }
 
@@ -5733,8 +5791,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
   public void setShowSeqFeatures(boolean b)
   {
-    showSeqFeatures.setSelected(true);
-    viewport.setShowSequenceFeatures(true);
+    showSeqFeatures.setSelected(b);
+    viewport.setShowSequenceFeatures(b);
   }
 
   /*
@@ -5906,6 +5964,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     for (AlignmentAnnotation aa : alignPanel.getAlignment()
             .getAlignmentAnnotation())
     {
+      /*
+       * don't display non-positional annotations on an alignment
+       */
+      if (aa.annotations == null)
+      {
+        continue;
+      }
       boolean apply = (aa.sequenceRef == null && forAlignment)
               || (aa.sequenceRef != null && forSequences);
       if (apply)