JAL-1619 modified repaint after 'Align As' action
[jalview.git] / src / jalview / gui / AlignFrame.java
index 07c4a54..8ff9eda 100644 (file)
@@ -30,6 +30,7 @@ import jalview.analysis.ParseProperties;
 import jalview.analysis.SequenceIdMatcher;
 import jalview.api.AlignViewControllerGuiI;
 import jalview.api.AlignViewControllerI;
+import jalview.api.AlignmentViewPanel;
 import jalview.api.analysis.ScoreModelI;
 import jalview.bin.Cache;
 import jalview.commands.CommandI;
@@ -83,6 +84,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.ws.jws1.Discoverer;
 import jalview.ws.jws2.Jws2Discoverer;
@@ -115,6 +117,7 @@ import java.beans.PropertyChangeEvent;
 import java.io.File;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
@@ -701,21 +704,110 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void setGUINucleotide(boolean nucleotide)
   {
     showTranslation.setVisible(nucleotide);
+    cdna.setVisible(!nucleotide);
     conservationMenuItem.setEnabled(!nucleotide);
     modifyConservation.setEnabled(!nucleotide);
     showGroupConservation.setEnabled(!nucleotide);
     rnahelicesColour.setEnabled(nucleotide);
     purinePyrimidineColour.setEnabled(nucleotide);
-    // Remember AlignFrame always starts as protein
-    // if (!nucleotide)
-    // {
-    // showTr
-    // calculateMenu.remove(calculateMenu.getItemCount() - 2);
-    // }
   }
 
   /**
-   * set up menus for the currently viewport. This may be called after any
+   * Builds codon mappings from this (protein) alignment to any compatible
+   * nucleotide alignments. Mappings are built between sequences with the same
+   * name and compatible lengths. Also makes the cDNA alignment a
+   * CommandListener for the protein alignment so that edits are mirrored.
+   */
+  @Override
+  protected void linkCdna_actionPerformed()
+  {
+    int linkedCount = 0;
+    int alreadyLinkedCount = 0;
+    final AlignmentI thisAlignment = this.alignPanel.getAlignment();
+
+    for (AlignFrame af : Desktop.getAlignframes())
+    {
+      if (af.alignPanel != null)
+      {
+        final AlignmentI thatAlignment = af.alignPanel.getAlignment();
+        if (thatAlignment.isNucleotide())
+        {
+          // TODO exclude an AlignFrame which is already mapped to this one
+          // temporary version: exclude if already a CommandListener (should
+          // cover most cases but not all)
+          final boolean alreadyMapped = this.viewport
+                  .getStructureSelectionManager().hasCommandListener(
+                          af.viewport);
+          if (alreadyMapped)
+          {
+            alreadyLinkedCount++;
+          }
+          else
+          {
+            boolean mapped = AlignmentUtils.mapProteinToCdna(thisAlignment,
+                    thatAlignment);
+            if (mapped)
+            {
+              final StructureSelectionManager ssm = StructureSelectionManager
+                      .getStructureSelectionManager(Desktop.instance);
+              ssm.addMappings(thisAlignment.getCodonFrames());
+              ssm.addCommandListener(af.getViewport());
+              linkedCount++;
+            }
+          }
+        }
+      }
+    }
+    String msg = "";
+    if (linkedCount == 0 && alreadyLinkedCount == 0)
+    {
+      msg = MessageManager.getString("label.no_cdna");
+    }
+    else if (linkedCount > 0)
+    {
+      msg = MessageManager.formatMessage("label.linked_cdna", linkedCount);
+    }
+    else
+    {
+      msg = MessageManager.formatMessage("label.cdna_all_linked",
+              alreadyLinkedCount);
+    }
+    setStatus(msg);
+  }
+
+  /**
+   * Align any linked cDNA to match the alignment of this (protein) alignment.
+   * Any mapped sequence regions will be realigned, unmapped sequences are not
+   * affected.
+   */
+  @Override
+  protected void alignCdna_actionPerformed()
+  {
+    int seqCount = 0;
+    int alignCount = 0;
+    final AlignmentI thisAlignment = this.alignPanel.getAlignment();
+    for (AlignFrame af : Desktop.getAlignframes())
+    {
+      if (af.alignPanel != null)
+      {
+        final AlignmentI thatAlignment = af.alignPanel.getAlignment();
+        if (thatAlignment.isNucleotide())
+        {
+          int seqsAligned = thatAlignment.alignAs(thisAlignment);
+          seqCount += seqsAligned;
+          if (seqsAligned > 0)
+          {
+            af.alignPanel.alignmentChanged();
+            alignCount++;
+          }
+        }
+      }
+    }
+    setStatus(MessageManager.formatMessage("label.cdna_aligned", seqCount,
+            alignCount));
+  }
+  /**
+   * set up menus for the current viewport. This may be called after any
    * operation that affects the data in the current view (selection changed,
    * etc) to update the menus to reflect the new state.
    */
@@ -1408,10 +1500,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   void updateEditMenuBar()
   {
 
-    if (viewport.historyList.size() > 0)
+    if (viewport.getHistoryList().size() > 0)
     {
       undoMenuItem.setEnabled(true);
-      CommandI command = viewport.historyList.peek();
+      CommandI command = viewport.getHistoryList().peek();
       undoMenuItem.setText(MessageManager.formatMessage(
               "label.undo_command", new String[]
               { command.getDescription() }));
@@ -1422,11 +1514,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       undoMenuItem.setText(MessageManager.getString("action.undo"));
     }
 
-    if (viewport.redoList.size() > 0)
+    if (viewport.getRedoList().size() > 0)
     {
       redoMenuItem.setEnabled(true);
 
-      CommandI command = viewport.redoList.peek();
+      CommandI command = viewport.getRedoList().peek();
       redoMenuItem.setText(MessageManager.formatMessage(
               "label.redo_command", new String[]
               { command.getDescription() }));
@@ -1442,8 +1534,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     if (command.getSize() > 0)
     {
-      viewport.historyList.push(command);
-      viewport.redoList.clear();
+      viewport.addToHistoryList(command);
+      viewport.clearRedoList();
       updateEditMenuBar();
       viewport.updateHiddenColumns();
       // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
@@ -1486,12 +1578,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void undoMenuItem_actionPerformed(ActionEvent e)
   {
-    if (viewport.historyList.empty())
+    if (viewport.getHistoryList().isEmpty())
     {
       return;
     }
-    CommandI command = viewport.historyList.pop();
-    viewport.redoList.push(command);
+    CommandI command = viewport.getHistoryList().pop();
+    viewport.addToRedoList(command);
+    // TODO: execute command before adding to redo list / broadcasting?
     command.undoCommand(getViewAlignments());
 
     AlignViewport originalSource = getOriginatingSource(command);
@@ -1524,13 +1617,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void redoMenuItem_actionPerformed(ActionEvent e)
   {
-    if (viewport.redoList.size() < 1)
+    if (viewport.getRedoList().size() < 1)
     {
       return;
     }
 
-    CommandI command = viewport.redoList.pop();
-    viewport.historyList.push(command);
+    CommandI command = viewport.getRedoList().pop();
+    viewport.addToHistoryList(command);
     command.doCommand(getViewAlignments());
 
     AlignViewport originalSource = getOriginatingSource(command);
@@ -1700,11 +1793,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
 
     boolean appendHistoryItem = false;
-    if (viewport.historyList != null && viewport.historyList.size() > 0
-            && viewport.historyList.peek() instanceof SlideSequencesCommand)
+    if (viewport.getHistoryList() != null
+            && viewport.getHistoryList().size() > 0
+            && viewport.getHistoryList().peek() instanceof SlideSequencesCommand)
     {
       appendHistoryItem = ssc
-              .appendSlideCommand((SlideSequencesCommand) viewport.historyList
+              .appendSlideCommand((SlideSequencesCommand) viewport
+                      .getHistoryList()
                       .peek());
     }
 
@@ -2598,6 +2693,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     new Finder();
   }
 
+  /**
+   * Create a new view of the current alignment.
+   */
   @Override
   public void newView_actionPerformed(ActionEvent e)
   {
@@ -2660,8 +2758,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       viewport.viewName = "Original";
     }
 
-    newap.av.historyList = viewport.historyList;
-    newap.av.redoList = viewport.redoList;
+    newap.av.setHistoryList(viewport.getHistoryList());
+    newap.av.setRedoList(viewport.getRedoList());
 
     int index = Desktop.getViewCount(viewport.getSequenceSetId());
     // make sure the new view has a unique name - this is essential for Jalview
@@ -4184,16 +4282,20 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
        */
       msa = viewport.getAlignmentView(true);
     }
+    else if (viewport.getSelectionGroup() != null
+            && viewport.getSelectionGroup().getSize() == 1)
+    {
+      int option = JOptionPane.showConfirmDialog(this,
+              MessageManager.getString("warn.oneseq_msainput_selection"),
+              MessageManager.getString("label.invalid_selection"),
+              JOptionPane.OK_CANCEL_OPTION);
+      if (option == JOptionPane.OK_OPTION)
+      {
+        msa = viewport.getAlignmentView(false);
+      }
+    }
     else
     {
-      /*
-       * Vector seqs = viewport.getAlignment().getSequences();
-       * 
-       * if (seqs.size() > 1) { msa = new SequenceI[seqs.size()];
-       * 
-       * for (int i = 0; i < seqs.size(); i++) { msa[i] = (SequenceI)
-       * seqs.elementAt(i); } }
-       */
       msa = viewport.getAlignmentView(false);
     }
     return msa;
@@ -4800,6 +4902,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
+  /**
+   * Construct and display a new frame containing the translation of this
+   * frame's cDNA sequences to their protein (amino acid) equivalents.
+   */
   @Override
   public void showTranslation_actionPerformed(ActionEvent e)
   {
@@ -4849,6 +4955,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       Desktop.addInternalFrame(af, MessageManager.formatMessage(
               "label.translation_of_params", new String[]
               { this.getTitle() }), DEFAULT_WIDTH, DEFAULT_HEIGHT);
+      viewport.getStructureSelectionManager().addCommandListener(viewport);
     }
   }
 
@@ -5816,6 +5923,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
     alignPanel.paintAlignment(true);
   }
+
+  /**
+   * 
+   * @return alignment panels in this alignemnt frame
+   */
+  public List<AlignmentViewPanel> getAlignPanels()
+  {
+    return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
+  }
 }
 
 class PrintThread extends Thread