From 3eef76298c55f3def21eed2516b5ace4405bed0a Mon Sep 17 00:00:00 2001 From: jprocter Date: Fri, 31 Aug 2012 11:22:23 +0100 Subject: [PATCH] JAL-1015 refactor tooltip html generation code to jalview.io.SequenceAnnotationReport --- src/jalview/gui/IdPanel.java | 60 +---- src/jalview/gui/SeqPanel.java | 145 +---------- src/jalview/io/SequenceAnnotationReport.java | 357 ++++++++++++++++++++++++++ 3 files changed, 368 insertions(+), 194 deletions(-) create mode 100644 src/jalview/io/SequenceAnnotationReport.java diff --git a/src/jalview/gui/IdPanel.java b/src/jalview/gui/IdPanel.java index 0480ffa..3b9d385 100755 --- a/src/jalview/gui/IdPanel.java +++ b/src/jalview/gui/IdPanel.java @@ -25,6 +25,7 @@ import java.util.Vector; import javax.swing.*; import jalview.datamodel.*; +import jalview.io.SequenceAnnotationReport; import jalview.util.UrlLink; /** @@ -52,6 +53,7 @@ public class IdPanel extends JPanel implements MouseListener, int lastid = -1; boolean mouseDragging = false; + private final SequenceAnnotationReport seqAnnotReport; /** * Creates a new IdPanel object. @@ -67,6 +69,7 @@ public class IdPanel extends JPanel implements MouseListener, alignPanel = parent; idCanvas = new IdCanvas(av); linkImageURL = getClass().getResource("/images/link.gif").toString(); + seqAnnotReport = new SequenceAnnotationReport(linkImageURL); setLayout(new BorderLayout()); add(idCanvas, BorderLayout.CENTER); addMouseListener(this); @@ -74,7 +77,6 @@ public class IdPanel extends JPanel implements MouseListener, addMouseWheelListener(this); ToolTipManager.sharedInstance().registerComponent(this); } - /** * DOCUMENT ME! * @@ -86,63 +88,15 @@ public class IdPanel extends JPanel implements MouseListener, { SeqPanel sp = alignPanel.seqPanel; int seq = Math.max(0, sp.findSeq(e)); - String tmp; if (seq > -1 && seq < av.getAlignment().getHeight()) { SequenceI sequence = av.getAlignment().getSequenceAt(seq); StringBuffer tip = new StringBuffer(); - tip.append(""); - - int maxWidth = 0; - if (sequence.getDescription() != null) - { - tmp = sequence.getDescription(); - tip.append("
" + tmp); - maxWidth = Math.max(maxWidth, tmp.length()); - } - - DBRefEntry[] dbrefs = sequence.getDatasetSequence().getDBRef(); - if (av.isShowDbRefs() && dbrefs != null) - { - for (int i = 0; i < dbrefs.length; i++) - { - tip.append("
"); - tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId(); - tip.append(tmp); - maxWidth = Math.max(maxWidth, tmp.length()); - } - } - - // ADD NON POSITIONAL SEQUENCE INFO - SequenceFeature[] features = sequence.getDatasetSequence() - .getSequenceFeatures(); - SequenceFeature[] tfeat = new SequenceFeature[1]; - if (av.isShowNpFeats() && features != null) - { - for (int i = 0; i < features.length; i++) - { - if (features[i].begin == 0 && features[i].end == 0) - { - int sz = -tip.length(); - tfeat[0] = features[i]; - sp.appendFeatures(tip, linkImageURL, 0, tfeat, - sp.seqCanvas.fr.minmax); - sz += tip.length(); - maxWidth = Math.max(maxWidth, sz); - } - } - } - - if (maxWidth > 60) - { - tip.insert(0, "
"); - tip.append("
"); - } - - tip.append(""); - + seqAnnotReport.createSequenceAnnotationReport(tip, sequence, + av.isShowDbRefs(), av.isShowNpFeats(), + sp.seqCanvas.fr.minmax); setToolTipText("" + sequence.getDisplayId(true) + " " - + tip.toString()); + + tip.toString()+""); } } diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index cdaa5b9..648c3a2 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -27,6 +27,7 @@ import javax.swing.*; import jalview.commands.*; import jalview.datamodel.*; +import jalview.io.SequenceAnnotationReport; import jalview.schemes.*; import jalview.structure.*; @@ -87,7 +88,7 @@ public class SeqPanel extends JPanel implements MouseListener, StringBuffer keyboardNo2; java.net.URL linkImageURL; - + private final SequenceAnnotationReport seqARep; StringBuffer tooltipText = new StringBuffer(""); String tmpString; @@ -107,6 +108,7 @@ public class SeqPanel extends JPanel implements MouseListener, public SeqPanel(AlignViewport av, AlignmentPanel ap) { linkImageURL = getClass().getResource("/images/link.gif"); + seqARep=new SequenceAnnotationReport(linkImageURL.toString()); ToolTipManager.sharedInstance().registerComponent(this); ToolTipManager.sharedInstance().setInitialDelay(0); ToolTipManager.sharedInstance().setDismissDelay(10000); @@ -713,7 +715,7 @@ public class SeqPanel extends JPanel implements MouseListener, SequenceFeature[] features = findFeaturesAtRes( sequence.getDatasetSequence(), rpos = sequence.findPosition(res)); - appendFeatures(tooltipText, linkImageURL.toString(), rpos, features, + seqARep.appendFeatures(tooltipText, rpos, features, this.ap.seqPanel.seqCanvas.fr.minmax); } if (tooltipText.length() == 6) // @@ -759,145 +761,6 @@ public class SeqPanel extends JPanel implements MouseListener, return lastp = p; } - /** - * appends the features at rpos to the given stringbuffer ready for display in - * a tooltip - * - * @param tooltipText2 - * @param linkImageURL - * @param rpos - * @param features - * TODO refactor to Jalview 'utilities' somehow. - */ - public void appendFeatures(StringBuffer tooltipText2, - String linkImageURL, int rpos, SequenceFeature[] features) - { - appendFeatures(tooltipText2, linkImageURL, rpos, features, null); - } - - public void appendFeatures(StringBuffer tooltipText2, String string, - int rpos, SequenceFeature[] features, Hashtable minmax) - { - String tmpString; - if (features != null) - { - for (int i = 0; i < features.length; i++) - { - if (features[i].getType().equals("disulfide bond")) - { - if (features[i].getBegin() == rpos - || features[i].getEnd() == rpos) - { - if (tooltipText2.length() > 6) - { - tooltipText2.append("
"); - } - tooltipText2.append("disulfide bond " + features[i].getBegin() - + ":" + features[i].getEnd()); - if (features[i].links != null) - { - tooltipText2.append(" "); - } - } - } - else - { - if (tooltipText2.length() > 6) - { - tooltipText2.append("
"); - } - // TODO: remove this hack to display link only features - boolean linkOnly = features[i].getValue("linkonly") != null; - if (!linkOnly) - { - tooltipText2.append(features[i].getType() + " "); - if (rpos != 0) - { - // we are marking a positional feature - tooltipText2.append(features[i].begin); - } - if (features[i].begin != features[i].end) - { - tooltipText2.append(" " + features[i].end); - } - - if (features[i].getDescription() != null - && !features[i].description.equals(features[i] - .getType())) - { - tmpString = features[i].getDescription(); - String tmp2up=tmpString.toUpperCase(); - int startTag = tmp2up.indexOf(""); - if (startTag > -1) - { - tmpString = tmpString.substring(startTag + 6); - tmp2up = tmp2up.substring(startTag+6); - } - int endTag = tmp2up.indexOf(""); - if (endTag > -1) - { - tmpString = tmpString.substring(0, endTag); - tmp2up = tmp2up.substring(0, endTag); - } - endTag = tmp2up.indexOf(""); - if (endTag > -1) - { - tmpString = tmpString.substring(0, endTag); - } - - if (startTag > -1) - { - tooltipText2.append("; " + tmpString); - } - else - { - if (tmpString.indexOf("<") > -1 - || tmpString.indexOf(">") > -1) - { - // The description does not specify html is to - // be used, so we must remove < > symbols - tmpString = tmpString.replaceAll("<", "<"); - tmpString = tmpString.replaceAll(">", ">"); - - tooltipText2.append("; "); - tooltipText2.append(tmpString); - - } - else - { - tooltipText2.append("; " + tmpString); - } - } - } - // check score should be shown - if (features[i].getScore() != Float.NaN) - { - float[][] rng = (minmax == null) ? null : ((float[][]) minmax - .get(features[i].getType())); - if (rng != null && rng[0] != null && rng[0][0] != rng[0][1]) - { - tooltipText2.append(" Score=" + features[i].getScore()); - } - } - if (features[i].getValue("status") != null) - { - String status = features[i].getValue("status").toString(); - if (status.length() > 0) - { - tooltipText2.append("; (" + features[i].getValue("status") - + ")"); - } - } - } - if (features[i].links != null) - { - tooltipText2.append(" "); - } - - } - } - } - } String lastTooltip; diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java new file mode 100644 index 0000000..8642446 --- /dev/null +++ b/src/jalview/io/SequenceAnnotationReport.java @@ -0,0 +1,357 @@ +package jalview.io; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Vector; + +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.util.UrlLink; + +/** + * generate HTML reports for a sequence + * + * @author jimp + */ +public class SequenceAnnotationReport +{ + final String linkImageURL; + + public SequenceAnnotationReport(String linkImageURL) + { + this.linkImageURL = linkImageURL; + } + + /** + * appends the features at rpos to the given stringbuffer ready for display in + * a tooltip + * + * @param tooltipText2 + * @param linkImageURL + * @param rpos + * @param features + * TODO refactor to Jalview 'utilities' somehow. + */ + public void appendFeatures(final StringBuffer tooltipText2, int rpos, + SequenceFeature[] features) + { + appendFeatures(tooltipText2, rpos, features, null); + } + + public void appendFeatures(final StringBuffer tooltipText2, int rpos, + SequenceFeature[] features, Hashtable minmax) + { + String tmpString; + if (features != null) + { + for (int i = 0; i < features.length; i++) + { + if (features[i].getType().equals("disulfide bond")) + { + if (features[i].getBegin() == rpos + || features[i].getEnd() == rpos) + { + if (tooltipText2.length() > 6) + { + tooltipText2.append("
"); + } + tooltipText2.append("disulfide bond " + features[i].getBegin() + + ":" + features[i].getEnd()); + } + } + else + { + if (tooltipText2.length() > 6) + { + tooltipText2.append("
"); + } + // TODO: remove this hack to display link only features + boolean linkOnly = features[i].getValue("linkonly") != null; + if (!linkOnly) + { + tooltipText2.append(features[i].getType() + " "); + if (rpos != 0) + { + // we are marking a positional feature + tooltipText2.append(features[i].begin); + } + if (features[i].begin != features[i].end) + { + tooltipText2.append(" " + features[i].end); + } + + if (features[i].getDescription() != null + && !features[i].description.equals(features[i] + .getType())) + { + tmpString = features[i].getDescription(); + String tmp2up = tmpString.toUpperCase(); + int startTag = tmp2up.indexOf(""); + if (startTag > -1) + { + tmpString = tmpString.substring(startTag + 6); + tmp2up = tmp2up.substring(startTag + 6); + } + int endTag = tmp2up.indexOf(""); + if (endTag > -1) + { + tmpString = tmpString.substring(0, endTag); + tmp2up = tmp2up.substring(0, endTag); + } + endTag = tmp2up.indexOf(""); + if (endTag > -1) + { + tmpString = tmpString.substring(0, endTag); + } + + if (startTag > -1) + { + tooltipText2.append("; " + tmpString); + } + else + { + if (tmpString.indexOf("<") > -1 + || tmpString.indexOf(">") > -1) + { + // The description does not specify html is to + // be used, so we must remove < > symbols + tmpString = tmpString.replaceAll("<", "<"); + tmpString = tmpString.replaceAll(">", ">"); + + tooltipText2.append("; "); + tooltipText2.append(tmpString); + + } + else + { + tooltipText2.append("; " + tmpString); + } + } + } + // check score should be shown + if (features[i].getScore() != Float.NaN) + { + float[][] rng = (minmax == null) ? null : ((float[][]) minmax + .get(features[i].getType())); + if (rng != null && rng[0] != null && rng[0][0] != rng[0][1]) + { + tooltipText2.append(" Score=" + features[i].getScore()); + } + } + if (features[i].getValue("status") != null) + { + String status = features[i].getValue("status").toString(); + if (status.length() > 0) + { + tooltipText2.append("; (" + features[i].getValue("status") + + ")"); + } + } + } + } + if (features[i].links != null) + { + if (linkImageURL != null) + { + tooltipText2.append(" "); + } + else + { + for (String urlstring : (Vector) features[i].links) + { + try + { + for (String[] urllink : createLinksFrom(null, urlstring)) + { + tooltipText2.append("
" + + (urllink[0].toLowerCase().equals(urllink[1].toLowerCase()) ? urllink[0] : (urllink[0]+ ":" + urllink[1])) + "
"); + } + } catch (Exception x) + { + System.err.println("problem when creating links from " + + urlstring); + x.printStackTrace(); + } + } + } + + } + } + } + } + + /** + * + * @param seq + * @param link + * @return String[][] { String[] { link target, link label, dynamic component + * inserted (if any), url }} + */ + public String[][] createLinksFrom(SequenceI seq, String link) + { + ArrayList urlSets = new ArrayList(); + ArrayList uniques=new ArrayList(); + UrlLink urlLink = new UrlLink(link); + if (!urlLink.isValid()) + { + System.err.println(urlLink.getInvalidMessage()); + return null; + } + final String target = urlLink.getTarget(); // link.substring(0, + // link.indexOf("|")); + final String label = urlLink.getLabel(); + if (seq != null && urlLink.isDynamic()) + { + + // collect matching db-refs + DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(seq.getDBRef(), + new String[] + { target }); + // collect id string too + String id = seq.getName(); + String descr = seq.getDescription(); + if (descr != null && descr.length() < 1) + { + descr = null; + } + if (dbr != null) + { + for (int r = 0; r < dbr.length; r++) + { + if (id != null && dbr[r].getAccessionId().equals(id)) + { + // suppress duplicate link creation for the bare sequence ID + // string with this link + id = null; + } + // create Bare ID link for this RUL + String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(), true); + if (urls != null) + { + for (int u = 0; u < urls.length; u += 2) + { + String unq=urls[u]+"|"+urls[u+1]; + if (!uniques.contains(unq)) + { + urlSets.add(new String[] + { target, label, urls[u], urls[u + 1] }); + uniques.add(unq); + } + } + } + } + } + if (id != null) + { + // create Bare ID link for this RUL + String[] urls = urlLink.makeUrls(id, true); + if (urls != null) + { + for (int u = 0; u < urls.length; u += 2) + { + String unq=urls[u]+"|"+urls[u+1]; + if (!uniques.contains(unq)) + { + urlSets.add(new String[] + { target, label, urls[u], urls[u + 1] }); + uniques.add(unq); + } + } + } + } + if (descr != null && urlLink.getRegexReplace() != null) + { + // create link for this URL from description only if regex matches + String[] urls = urlLink.makeUrls(descr, true); + if (urls != null) + { + for (int u = 0; u < urls.length; u += 2) + { + String unq=urls[u]+"|"+urls[u+1]; + if (!uniques.contains(unq)) + { + urlSets.add(new String[] + { target, label, urls[u], urls[u + 1] }); + uniques.add(unq); + } + } + } + } + + } else { + String unq=label + "|" + urlLink.getUrl_prefix(); + if (!uniques.contains(unq)){ + uniques.add(unq); + // Add a non-dynamic link + urlSets.add(new String[] {target, label, null, urlLink.getUrl_prefix()}); + } + } + + return urlSets.toArray(new String[][] + {}); + } + + + public void createSequenceAnnotationReport(final StringBuffer tip, + SequenceI sequence, boolean showDbRefs, boolean showNpFeats, + Hashtable minmax) + { + createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats, true, minmax); + } + + public void createSequenceAnnotationReport(final StringBuffer tip, + SequenceI sequence, boolean showDbRefs, boolean showNpFeats, boolean tableWrap, + Hashtable minmax) + { + String tmp; + tip.append(""); + + int maxWidth = 0; + if (sequence.getDescription() != null) + { + tmp = sequence.getDescription(); + tip.append("
" + tmp); + maxWidth = Math.max(maxWidth, tmp.length()); + } + + DBRefEntry[] dbrefs = sequence.getDatasetSequence().getDBRef(); + if (showDbRefs && dbrefs != null) + { + for (int i = 0; i < dbrefs.length; i++) + { + tip.append("
"); + tmp = dbrefs[i].getSource() + " " + dbrefs[i].getAccessionId(); + tip.append(tmp); + maxWidth = Math.max(maxWidth, tmp.length()); + } + } + + // ADD NON POSITIONAL SEQUENCE INFO + SequenceFeature[] features = sequence.getDatasetSequence() + .getSequenceFeatures(); + SequenceFeature[] tfeat = new SequenceFeature[1]; + if (showNpFeats && features != null) + { + for (int i = 0; i < features.length; i++) + { + if (features[i].begin == 0 && features[i].end == 0) + { + int sz = -tip.length(); + tfeat[0] = features[i]; + appendFeatures(tip, 0, tfeat, minmax); + sz += tip.length(); + maxWidth = Math.max(maxWidth, sz); + } + } + } + + if (tableWrap && maxWidth > 60) + { + tip.insert(0, "
"); + tip.append("
"); + } + + } +} -- 1.7.10.2