JAL-1723 tooltip dbrefs sorted and limited to two per source
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 12 Apr 2016 12:00:38 +0000 (13:00 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 12 Apr 2016 12:00:38 +0000 (13:00 +0100)
src/jalview/appletgui/APopupMenu.java
src/jalview/gui/IdPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/SeqPanel.java
src/jalview/io/SequenceAnnotationReport.java

index 748954a..7fc88bc 100644 (file)
@@ -537,6 +537,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
     MenuItem item = new MenuItem(label);
     item.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         ap.alignFrame.showURL(url, target);
@@ -545,6 +546,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
     linkMenu.add(item);
   }
 
+  @Override
   public void itemStateChanged(ItemEvent evt)
   {
     if (evt.getSource() == abovePIDColour)
@@ -569,6 +571,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
     }
   }
 
+  @Override
   public void actionPerformed(ActionEvent evt)
   {
     Object source = evt.getSource();
@@ -850,7 +853,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
 
     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, ap.alignFrame);
 
-    StringBuffer contents = new StringBuffer();
+    StringBuilder contents = new StringBuilder(128);
     for (SequenceI seq : sequences)
     {
       contents.append(MessageManager.formatMessage(
@@ -861,7 +864,6 @@ public class APopupMenu extends java.awt.PopupMenu implements
               seq,
               true,
               true,
-              false,
               (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr
                       .getMinMax() : null);
       contents.append("</p>");
index bbffbab..c3ede0b 100755 (executable)
@@ -108,8 +108,8 @@ public class IdPanel extends JPanel implements MouseListener,
     if (seq > -1 && seq < av.getAlignment().getHeight())
     {
       SequenceI sequence = av.getAlignment().getSequenceAt(seq);
-      StringBuffer tip = new StringBuffer(64);
-      seqAnnotReport.createSequenceAnnotationReport(tip, sequence,
+      StringBuilder tip = new StringBuilder(64);
+      seqAnnotReport.createTooltipAnnotationReport(tip, sequence,
               av.isShowDBRefs(), av.isShowNPFeats(),
               sp.seqCanvas.fr.getMinMax());
       setToolTipText(JvSwingUtils.wrapTooltip(true,
index ab8c398..008de18 100644 (file)
@@ -1738,7 +1738,7 @@ public class PopupMenu extends JPopupMenu
   public void createSequenceDetailsReport(SequenceI[] sequences)
   {
     CutAndPasteHtmlTransfer cap = new CutAndPasteHtmlTransfer();
-    StringBuffer contents = new StringBuffer();
+    StringBuilder contents = new StringBuilder(128);
     for (SequenceI seq : sequences)
     {
       contents.append("<p><h2>"
@@ -1753,7 +1753,6 @@ public class PopupMenu extends JPopupMenu
                       seq,
                       true,
                       true,
-                      false,
                       (ap.getSeqPanel().seqCanvas.fr != null) ? ap
                               .getSeqPanel().seqCanvas.fr.getMinMax()
                               : null);
index cce2ee0..e94e94f 100644 (file)
@@ -121,7 +121,7 @@ public class SeqPanel extends JPanel implements MouseListener,
 
   private final SequenceAnnotationReport seqARep;
 
-  StringBuffer tooltipText = new StringBuffer();
+  StringBuilder tooltipText = new StringBuilder();
 
   String tmpString;
 
index d3a1d09..96d71f6 100644 (file)
@@ -26,6 +26,9 @@ import jalview.datamodel.SequenceI;
 import jalview.util.UrlLink;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Hashtable;
 import java.util.List;
 
@@ -38,6 +41,29 @@ public class SequenceAnnotationReport
 {
   final String linkImageURL;
 
+  /*
+   * Comparator to order DBRefEntry by Source + accession id (case-insensitive)
+   */
+  private static Comparator<DBRefEntry> comparator = new Comparator<DBRefEntry>()
+  {
+    @Override
+    public int compare(DBRefEntry ref1, DBRefEntry ref2)
+    {
+      String s1 = ref1.getSource();
+      String s2 = ref2.getSource();
+      int comp = s1 == null ? -1 : (s2 == null ? 1 : s1
+              .compareToIgnoreCase(s2));
+      if (comp == 0)
+      {
+        String a1 = ref1.getAccessionId();
+        String a2 = ref2.getAccessionId();
+        comp = a1 == null ? -1 : (a2 == null ? 1 : a1
+                .compareToIgnoreCase(a2));
+      }
+      return comp;
+    }
+  };
+
   public SequenceAnnotationReport(String linkImageURL)
   {
     this.linkImageURL = linkImageURL;
@@ -47,19 +73,14 @@ public class SequenceAnnotationReport
    * appends the features at rpos to the given stringbuffer ready for display in
    * a tooltip
    * 
-   * @param tooltipText2
+   * @param tooltipText
    * @param linkImageURL
    * @param rpos
    * @param features
+   * @param minmax
    *          TODO refactor to Jalview 'utilities' somehow.
    */
-  public void appendFeatures(final StringBuffer tooltipText2, int rpos,
-          List<SequenceFeature> features)
-  {
-    appendFeatures(tooltipText2, rpos, features, null);
-  }
-
-  public void appendFeatures(final StringBuffer tooltipText2, int rpos,
+  public void appendFeatures(final StringBuilder tooltipText, int rpos,
           List<SequenceFeature> features, Hashtable minmax)
   {
     String tmpString;
@@ -71,33 +92,33 @@ public class SequenceAnnotationReport
         {
           if (feature.getBegin() == rpos || feature.getEnd() == rpos)
           {
-            if (tooltipText2.length() > 6)
+            if (tooltipText.length() > 6)
             {
-              tooltipText2.append("<br>");
+              tooltipText.append("<br>");
             }
-            tooltipText2.append("disulfide bond " + feature.getBegin()
+            tooltipText.append("disulfide bond " + feature.getBegin()
                     + ":" + feature.getEnd());
           }
         }
         else
         {
-          if (tooltipText2.length() > 6)
+          if (tooltipText.length() > 6)
           {
-            tooltipText2.append("<br>");
+            tooltipText.append("<br>");
           }
           // TODO: remove this hack to display link only features
           boolean linkOnly = feature.getValue("linkonly") != null;
           if (!linkOnly)
           {
-            tooltipText2.append(feature.getType() + " ");
+            tooltipText.append(feature.getType() + " ");
             if (rpos != 0)
             {
               // we are marking a positional feature
-              tooltipText2.append(feature.begin);
+              tooltipText.append(feature.begin);
             }
             if (feature.begin != feature.end)
             {
-              tooltipText2.append(" " + feature.end);
+              tooltipText.append(" " + feature.end);
             }
 
             if (feature.getDescription() != null
@@ -125,7 +146,7 @@ public class SequenceAnnotationReport
 
               if (startTag > -1)
               {
-                tooltipText2.append("; " + tmpString);
+                tooltipText.append("; " + tmpString);
               }
               else
               {
@@ -137,13 +158,13 @@ public class SequenceAnnotationReport
                   tmpString = tmpString.replaceAll("<", "&lt;");
                   tmpString = tmpString.replaceAll(">", "&gt;");
 
-                  tooltipText2.append("; ");
-                  tooltipText2.append(tmpString);
+                  tooltipText.append("; ");
+                  tooltipText.append(tmpString);
 
                 }
                 else
                 {
-                  tooltipText2.append("; " + tmpString);
+                  tooltipText.append("; " + tmpString);
                 }
               }
             }
@@ -154,7 +175,7 @@ public class SequenceAnnotationReport
                       .get(feature.getType()));
               if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
               {
-                tooltipText2.append(" Score=" + feature.getScore());
+                tooltipText.append(" Score=" + feature.getScore());
               }
             }
             if (feature.getValue("status") != null)
@@ -162,7 +183,7 @@ public class SequenceAnnotationReport
               String status = feature.getValue("status").toString();
               if (status.length() > 0)
               {
-                tooltipText2.append("; (" + feature.getValue("status")
+                tooltipText.append("; (" + feature.getValue("status")
                         + ")");
               }
             }
@@ -172,7 +193,7 @@ public class SequenceAnnotationReport
         {
           if (linkImageURL != null)
           {
-            tooltipText2.append(" <img src=\"" + linkImageURL + "\">");
+            tooltipText.append(" <img src=\"" + linkImageURL + "\">");
           }
           else
           {
@@ -182,7 +203,7 @@ public class SequenceAnnotationReport
               {
                 for (String[] urllink : createLinksFrom(null, urlstring))
                 {
-                  tooltipText2.append("<br/> <a href=\""
+                  tooltipText.append("<br/> <a href=\""
                           + urllink[3]
                           + "\" target=\""
                           + urllink[0]
@@ -319,26 +340,55 @@ public class SequenceAnnotationReport
     return urlSets.toArray(new String[][] {});
   }
 
-  public void createSequenceAnnotationReport(final StringBuffer tip,
+  public void createTooltipAnnotationReport(final StringBuilder tip,
           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
           Hashtable minmax)
   {
-    createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats,
-            true, minmax);
+    int maxWidth = createSequenceAnnotationReport(tip, sequence,
+            showDbRefs, showNpFeats, minmax, true);
+
+    if (maxWidth > 60)
+    {
+      tip.insert(0, "<table width=350 border=0><tr><td><i>");
+      tip.append("</i></td></tr></table>");
+    }
   }
 
-  public void createSequenceAnnotationReport(final StringBuffer tip,
+  public int createSequenceAnnotationReport(final StringBuilder tip,
+          SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
+          Hashtable minmax)
+  {
+    return createSequenceAnnotationReport(tip, sequence, showDbRefs,
+            showNpFeats, minmax, false);
+  }
+
+  /**
+   * Adds an html-formatted sequence annotation report to the provided string
+   * buffer, and returns the longest line length added
+   * 
+   * @param sb
+   * @param sequence
+   * @param showDbRefs
+   *          if true, include database references
+   * @param showNpFeats
+   *          if true, include non-positional sequence features
+   * @param minmax
+   * @param summary
+   *          if true, build a shortened summary report (for tooltip)
+   * @return
+   */
+  int createSequenceAnnotationReport(final StringBuilder sb,
           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
-          boolean tableWrap, Hashtable minmax)
+          Hashtable minmax, boolean summary)
   {
     String tmp;
-    tip.append("<i>");
+    sb.append("<i>");
 
     int maxWidth = 0;
     if (sequence.getDescription() != null)
     {
       tmp = sequence.getDescription();
-      tip.append("<br>" + tmp);
+      sb.append("<br>").append(tmp);
       maxWidth = Math.max(maxWidth, tmp.length());
     }
     SequenceI ds = sequence;
@@ -347,14 +397,55 @@ public class SequenceAnnotationReport
       ds = ds.getDatasetSequence();
     }
     DBRefEntry[] dbrefs = ds.getDBRefs();
+    Arrays.sort(dbrefs, comparator);
     if (showDbRefs && dbrefs != null)
     {
-      for (int i = 0; i < dbrefs.length; i++)
+      boolean ellipsis = false;
+      String lastSource = null;
+      int countForSource = 0;
+      for (DBRefEntry ref : dbrefs)
       {
-        tip.append("<br>");
-        tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId();
-        tip.append(tmp);
-        maxWidth = Math.max(maxWidth, tmp.length());
+        String source = ref.getSource();
+        if (source == null)
+        {
+          // shouldn't happen
+          continue;
+        }
+        boolean sourceChanged = !source.equals(lastSource);
+        if (sourceChanged)
+        {
+          countForSource = 0;
+        }
+        lastSource = source;
+        countForSource++;
+        if (countForSource == 1 || !summary)
+        {
+          sb.append("<br>");
+        }
+        if (countForSource < 3 || !summary)
+        {
+          String accessionId = ref.getAccessionId();
+          int len = accessionId.length() + 1;
+          if (countForSource > 1 && summary)
+          {
+            sb.append(", ").append(accessionId);
+            len++;
+          }
+          else
+          {
+            sb.append(source).append(" ").append(accessionId);
+            len += source.length();
+          }
+          maxWidth = Math.max(maxWidth, len);
+        }
+        if (countForSource == 3 && summary)
+        {
+          sb.append(", ...");
+          ellipsis = true;
+        }
+      }
+      if (ellipsis) {
+        sb.append("<br>(Output Sequence Details to list all database references)");
       }
     }
 
@@ -366,21 +457,15 @@ public class SequenceAnnotationReport
       {
         if (features[i].begin == 0 && features[i].end == 0)
         {
-          int sz = -tip.length();
-          List<SequenceFeature> tfeat = new ArrayList<SequenceFeature>();
-          tfeat.add(features[i]);
-          appendFeatures(tip, 0, tfeat, minmax);
-          sz += tip.length();
+          int sz = -sb.length();
+          List<SequenceFeature> tfeat = Collections
+                  .singletonList(features[i]);
+          appendFeatures(sb, 0, tfeat, minmax);
+          sz += sb.length();
           maxWidth = Math.max(maxWidth, sz);
         }
       }
     }
-
-    if (tableWrap && maxWidth > 60)
-    {
-      tip.insert(0, "<table width=350 border=0><tr><td><i>");
-      tip.append("</i></td></tr></table>");
-    }
-
+    return maxWidth;
   }
 }