JAL-3725 restrict mapped virtual feature location to mapped region
[jalview.git] / src / jalview / gui / PopupMenu.java
index 187090b..abe9835 100644 (file)
  */
 package jalview.gui;
 
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JColorChooser;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+import javax.swing.JRadioButtonMenuItem;
+
 import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.analysis.AlignmentUtils;
@@ -56,31 +81,6 @@ import jalview.util.StringUtils;
 import jalview.util.UrlLink;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
 
-import java.awt.Color;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.Vector;
-
-import javax.swing.ButtonGroup;
-import javax.swing.JCheckBoxMenuItem;
-import javax.swing.JColorChooser;
-import javax.swing.JMenu;
-import javax.swing.JMenuItem;
-import javax.swing.JPopupMenu;
-import javax.swing.JRadioButtonMenuItem;
-
 /**
  * The popup menu that is displayed on right-click on a sequence id, or in the
  * sequence alignment.
@@ -755,14 +755,16 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
   }
 
   /**
-   * Add a link to show feature details for each sequence feature
+   * Add a menu item to show feature details for each sequence feature. Any
+   * linked 'virtual' features (CDS/protein) are also optionally found and
+   * included.
    * 
    * @param features
-   * @param column
    * @param seq
+   * @param column
    */
   protected void addFeatureDetails(List<SequenceFeature> features,
-          SequenceI seq, int column)
+          final SequenceI seq, final int column)
   {
     /*
      * add features in CDS/protein complement at the corresponding
@@ -797,39 +799,61 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     String name = seq.getName();
     for (final SequenceFeature sf : features)
     {
-      addFeatureDetailsMenuItem(details, name, sf);
+      addFeatureDetailsMenuItem(details, name, sf, null);
     }
 
     if (mf != null)
     {
-      name = mf.fromSeq == seq ? mf.mapping.getTo().getName()
-              : mf.fromSeq.getName();
       for (final SequenceFeature sf : mf.features)
       {
-        addFeatureDetailsMenuItem(details, name, sf);
+        addFeatureDetailsMenuItem(details, name, sf, mf);
       }
     }
   }
 
   /**
-   * A helper method to add one menu item whose action is to show details for one
-   * feature. The menu text includes feature description, but this may be
+   * A helper method to add one menu item whose action is to show details for
+   * one feature. The menu text includes feature description, but this may be
    * truncated.
    * 
    * @param details
    * @param seqName
    * @param sf
+   * @param mf
    */
   void addFeatureDetailsMenuItem(JMenu details, final String seqName,
-          final SequenceFeature sf)
+          final SequenceFeature sf, MappedFeatures mf)
   {
     int start = sf.getBegin();
     int end = sf.getEnd();
+    if (mf != null)
+    {
+      /*
+       * show local rather than linked feature coordinates
+       */
+      int[] beginRange = mf.getMappedPositions(start, start);
+      int[] endRange = mf.getMappedPositions(end, end);
+      if (beginRange == null || endRange == null)
+      {
+        // e.g. variant extending to stop codon so not mappable
+        return;
+      }
+      start = beginRange[0];
+      end = endRange[endRange.length - 1];
+      int[] localRange = mf.getMappedPositions(start, end);
+      if (localRange == null)
+      {
+        return;
+      }
+      start = localRange[0];
+      end = localRange[localRange.length - 1];
+    }
     StringBuilder desc = new StringBuilder();
     desc.append(sf.getType()).append(" ").append(String.valueOf(start));
     if (start != end)
     {
-      desc.append("-").append(String.valueOf(end));
+      desc.append(sf.isContactFeature() ? ":" : "-");
+      desc.append(String.valueOf(end));
     }
     String description = sf.getDescription();
     if (description != null)
@@ -860,26 +884,27 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        showFeatureDetails(seqName, sf);
+        showFeatureDetails(sf, seqName, mf);
       }
     });
     details.add(item);
   }
 
   /**
-   * Opens a panel showing a text report of feature dteails
-   * 
-   * @param seqName
+   * Opens a panel showing a text report of feature details
    * 
    * @param sf
+   * @param seqName
+   * @param mf
    */
-  protected void showFeatureDetails(String seqName, SequenceFeature sf)
+  protected void showFeatureDetails(SequenceFeature sf, String seqName,
+          MappedFeatures mf)
   {
     CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
     // it appears Java's CSS does not support border-collapse :-(
     cap.addStylesheetRule("table { border-collapse: collapse;}");
     cap.addStylesheetRule("table, td, th {border: 1px solid black;}");
-    cap.setText(sf.getDetailsReport(seqName));
+    cap.setText(sf.getDetailsReport(seqName, mf));
 
     Desktop.addInternalFrame(cap,
             MessageManager.getString("label.feature_details"), 500, 500);
@@ -1763,7 +1788,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
               "label.create_sequence_details_report_annotation_for",
               new Object[]
               { seq.getDisplayId(true) }) + "</h2></p><p>");
-      new SequenceAnnotationReport(null).createSequenceAnnotationReport(
+      new SequenceAnnotationReport(false).createSequenceAnnotationReport(
               contents, seq, true, true, ap.getSeqPanel().seqCanvas.fr);
       contents.append("</p>");
     }