From 054cc21f3aad9e37c464b1af6c62dbee6ca624b1 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Tue, 12 Apr 2016 13:00:38 +0100 Subject: [PATCH] JAL-1723 tooltip dbrefs sorted and limited to two per source --- src/jalview/appletgui/APopupMenu.java | 6 +- src/jalview/gui/IdPanel.java | 4 +- src/jalview/gui/PopupMenu.java | 3 +- src/jalview/gui/SeqPanel.java | 2 +- src/jalview/io/SequenceAnnotationReport.java | 181 +++++++++++++++++++------- 5 files changed, 141 insertions(+), 55 deletions(-) diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java index 748954a..7fc88bc 100644 --- a/src/jalview/appletgui/APopupMenu.java +++ b/src/jalview/appletgui/APopupMenu.java @@ -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("

"); diff --git a/src/jalview/gui/IdPanel.java b/src/jalview/gui/IdPanel.java index bbffbab..c3ede0b 100755 --- a/src/jalview/gui/IdPanel.java +++ b/src/jalview/gui/IdPanel.java @@ -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, diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index ab8c398..008de18 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -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("

" @@ -1753,7 +1753,6 @@ public class PopupMenu extends JPopupMenu seq, true, true, - false, (ap.getSeqPanel().seqCanvas.fr != null) ? ap .getSeqPanel().seqCanvas.fr.getMinMax() : null); diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index cce2ee0..e94e94f 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -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; diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java index d3a1d09..96d71f6 100644 --- a/src/jalview/io/SequenceAnnotationReport.java +++ b/src/jalview/io/SequenceAnnotationReport.java @@ -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 comparator = new Comparator() + { + @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 features) - { - appendFeatures(tooltipText2, rpos, features, null); - } - - public void appendFeatures(final StringBuffer tooltipText2, int rpos, + public void appendFeatures(final StringBuilder tooltipText, int rpos, List 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("
"); + tooltipText.append("
"); } - 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("
"); + tooltipText.append("
"); } // 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("<", "<"); tmpString = tmpString.replaceAll(">", ">"); - 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(" "); + tooltipText.append(" "); } else { @@ -182,7 +203,7 @@ public class SequenceAnnotationReport { for (String[] urllink : createLinksFrom(null, urlstring)) { - tooltipText2.append("
60) + { + tip.insert(0, "
"); + tip.append("
"); + } } - 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(""); + sb.append(""); int maxWidth = 0; if (sequence.getDescription() != null) { tmp = sequence.getDescription(); - tip.append("
" + tmp); + sb.append("
").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("
"); - 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("
"); + } + 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("
(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 tfeat = new ArrayList(); - tfeat.add(features[i]); - appendFeatures(tip, 0, tfeat, minmax); - sz += tip.length(); + int sz = -sb.length(); + List 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, "
"); - tip.append("
"); - } - + return maxWidth; } } -- 1.7.10.2