X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FAnnotationLabels.java;h=bf3ecf2e470dad3e992e8a5049cf64268fe37f40;hb=933e28e48b4f3bf98851cedd99ef345d45bf25a3;hp=2e70ca1bff37b4be255d41afc7b4ef49334e3547;hpb=51d3f6808e74f158d2ba4807ae4dbf6001b94e2b;p=jalview.git diff --git a/src/jalview/gui/AnnotationLabels.java b/src/jalview/gui/AnnotationLabels.java index 2e70ca1..bf3ecf2 100755 --- a/src/jalview/gui/AnnotationLabels.java +++ b/src/jalview/gui/AnnotationLabels.java @@ -55,7 +55,6 @@ import java.awt.geom.AffineTransform; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; -import java.util.regex.Pattern; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenuItem; @@ -72,6 +71,10 @@ import javax.swing.ToolTipManager; public class AnnotationLabels extends JPanel implements MouseListener, MouseMotionListener, ActionListener { + private static final String HTML_END_TAG = ""; + + private static final String HTML_START_TAG = ""; + /** * width in pixels within which height adjuster arrows are shown and active */ @@ -82,9 +85,6 @@ public class AnnotationLabels extends JPanel */ private static int HEIGHT_ADJUSTER_HEIGHT = 10; - private static final Pattern LEFT_ANGLE_BRACKET_PATTERN = Pattern - .compile("<"); - private static final Font font = new Font("Arial", Font.PLAIN, 11); private static final String TOGGLE_LABELSCALE = MessageManager @@ -366,9 +366,9 @@ public class AnnotationLabels extends JPanel // JAL-1264 hide all sequence-specific annotations of this type if (selectedRow < aa.length) { - if (isSequenceAnnotation) + if (aa[selectedRow].sequenceRef != null) { - final String label = ann.label; + final String label = aa[selectedRow].label; JMenuItem hideType = new JMenuItem(); String text = MessageManager.getString("label.hide_all") + " " + label; @@ -403,24 +403,28 @@ public class AnnotationLabels extends JPanel // property methods if (selectedRow < aa.length) { - final String label = ann.label; - if (!(ann.autoCalculated) + final String label = aa[selectedRow].label; + if (!(aa[selectedRow].autoCalculated) && !(InformationThread.HMM_CALC_ID.equals(ann.getCalcId()))) { - if (ann.graph == AlignmentAnnotation.NO_GRAPH) + if (aa[selectedRow].graph == AlignmentAnnotation.NO_GRAPH) { // display formatting settings for this row. pop.addSeparator(); // av and sequencegroup need to implement same interface for item = new JCheckBoxMenuItem(TOGGLE_LABELSCALE, - ann.scaleColLabel); + aa[selectedRow].scaleColLabel); item.addActionListener(this); pop.add(item); } } else if (label.indexOf("Consensus") > -1) { - addConsensusMenu(pop, ann); + addConsensusMenuOptions(ap, aa[selectedRow], pop); + + final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ); + consclipbrd.addActionListener(this); + pop.add(consclipbrd); } else if (InformationThread.HMM_CALC_ID.equals(ann.getCalcId())) { @@ -457,13 +461,15 @@ public class AnnotationLabels extends JPanel if (!ann.groupRef.isUseInfoLetterHeight()) { ann.groupRef.setIgnoreBelowBackground(cbmi.getState()); + // todo and recompute group annotation } } else if (!ap.av.isInfoLetterHeight()) { ap.av.setIgnoreBelowBackground(cbmi.getState(), ap); + // todo and recompute annotation } - ap.alignmentChanged(); + ap.alignmentChanged(); // todo not like this } }); pop.add(cbmi); @@ -480,11 +486,13 @@ public class AnnotationLabels extends JPanel { ann.groupRef.setInfoLetterHeight((letterHeight.getState())); ann.groupRef.setIgnoreBelowBackground(true); + // todo and recompute group annotation } else { ap.av.setInfoLetterHeight(letterHeight.getState(), ap); ap.av.setIgnoreBelowBackground(true, ap); + // todo and recompute annotation } ap.alignmentChanged(); } @@ -513,7 +521,7 @@ public class AnnotationLabels extends JPanel @Override public void actionPerformed(ActionEvent e) { - ann.groupRef.setshowHMMSequenceLogo(cprofl.getState()); + ann.groupRef.setShowHMMSequenceLogo(cprofl.getState()); ap.repaint(); } }); @@ -529,7 +537,7 @@ public class AnnotationLabels extends JPanel ann.groupRef .setNormaliseHMMSequenceLogo(cproflnorm.getState()); // automatically enable logo display if we're clicked - ann.groupRef.setshowHMMSequenceLogo(true); + ann.groupRef.setShowHMMSequenceLogo(true); ap.repaint(); } }); @@ -581,30 +589,37 @@ public class AnnotationLabels extends JPanel } /** - * Adds context menu options for (alignment or group) Consensus annotation + * A helper method that adds menu options for calculation and visualisation of + * group and/or alignment consensus annotation to a popup menu. This is + * designed to be reusable for either unwrapped mode (popup menu is shown on + * component AnnotationLabels), or wrapped mode (popup menu is shown on + * IdPanel when the mouse is over an annotation label). * - * @param pop + * @param ap * @param ann + * @param pop */ - protected void addConsensusMenu(JPopupMenu pop, - final AlignmentAnnotation ann) + static void addConsensusMenuOptions(AlignmentPanel ap, + AlignmentAnnotation ann, + JPopupMenu pop) { - final boolean isGroupAnnotation = ann.groupRef != null; pop.addSeparator(); final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem( MessageManager.getString("label.ignore_gaps_consensus"), - (ann.groupRef != null) - ? ann.groupRef.isIgnoreGapsConsensus() + (ann.groupRef != null) ? ann.groupRef.getIgnoreGapsConsensus() : ap.av.isIgnoreGapsConsensus()); + final AlignmentAnnotation aaa = ann; cbmi.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (isGroupAnnotation) + if (aaa.groupRef != null) { - ann.groupRef.setIgnoreGapsConsensus(cbmi.getState()); + aaa.groupRef.setIgnoreGapsConsensus(cbmi.getState()); + ap.getAnnotationPanel() + .paint(ap.getAnnotationPanel().getGraphics()); } else { @@ -614,7 +629,8 @@ public class AnnotationLabels extends JPanel } }); pop.add(cbmi); - if (isGroupAnnotation) + + if (aaa.groupRef != null) { /* * group consensus options @@ -627,7 +643,7 @@ public class AnnotationLabels extends JPanel @Override public void actionPerformed(ActionEvent e) { - ann.groupRef.setShowConsensusHistogram(chist.getState()); + aaa.groupRef.setShowConsensusHistogram(chist.getState()); ap.repaint(); } }); @@ -640,7 +656,7 @@ public class AnnotationLabels extends JPanel @Override public void actionPerformed(ActionEvent e) { - ann.groupRef.setshowSequenceLogo(cprofl.getState()); + aaa.groupRef.setshowSequenceLogo(cprofl.getState()); ap.repaint(); } }); @@ -653,9 +669,9 @@ public class AnnotationLabels extends JPanel @Override public void actionPerformed(ActionEvent e) { - ann.groupRef.setNormaliseSequenceLogo(cproflnorm.getState()); + aaa.groupRef.setNormaliseSequenceLogo(cproflnorm.getState()); // automatically enable logo display if we're clicked - ann.groupRef.setshowSequenceLogo(true); + aaa.groupRef.setshowSequenceLogo(true); ap.repaint(); } }); @@ -668,48 +684,48 @@ public class AnnotationLabels extends JPanel */ final JCheckBoxMenuItem chist = new JCheckBoxMenuItem( MessageManager.getString("label.show_histogram"), - av.isShowConsensusHistogram()); + ap.av.isShowConsensusHistogram()); chist.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - av.setShowConsensusHistogram(chist.getState()); + ap.av.setShowConsensusHistogram(chist.getState()); + ap.alignFrame.setMenusForViewport(); ap.repaint(); } }); pop.add(chist); final JCheckBoxMenuItem cprof = new JCheckBoxMenuItem( MessageManager.getString("label.show_logo"), - av.isShowSequenceLogo()); + ap.av.isShowSequenceLogo()); cprof.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - av.setShowSequenceLogo(cprof.getState()); + ap.av.setShowSequenceLogo(cprof.getState()); + ap.alignFrame.setMenusForViewport(); ap.repaint(); } }); pop.add(cprof); final JCheckBoxMenuItem cprofnorm = new JCheckBoxMenuItem( MessageManager.getString("label.normalise_logo"), - av.isNormaliseSequenceLogo()); + ap.av.isNormaliseSequenceLogo()); cprofnorm.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - av.setShowSequenceLogo(true); - av.setNormaliseSequenceLogo(cprofnorm.getState()); + ap.av.setShowSequenceLogo(true); + ap.av.setNormaliseSequenceLogo(cprofnorm.getState()); + ap.alignFrame.setMenusForViewport(); ap.repaint(); } }); pop.add(cprofnorm); } - final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ); - consclipbrd.addActionListener(this); - pop.add(consclipbrd); } /** @@ -822,73 +838,123 @@ public class AnnotationLabels extends JPanel if (selectedRow > -1 && ap.av.getAlignment() .getAlignmentAnnotation().length > selectedRow) { - AlignmentAnnotation aa = ap.av.getAlignment() - .getAlignmentAnnotation()[selectedRow]; + AlignmentAnnotation[] anns = ap.av.getAlignment() + .getAlignmentAnnotation(); + AlignmentAnnotation aa = anns[selectedRow]; + + String desc = getTooltip(aa); + this.setToolTipText(desc); + String msg = getStatusMessage(aa, anns); + ap.alignFrame.setStatus(msg); + } + } - StringBuffer desc = new StringBuffer(); - if (aa.description != null - && !aa.description.equals("New description")) + /** + * Constructs suitable text to show in the status bar when over an annotation + * label, containing the associated sequence name (if any), and the annotation + * labels (or all labels for a graph group annotation) + * + * @param aa + * @param anns + * @return + */ + static String getStatusMessage(AlignmentAnnotation aa, + AlignmentAnnotation[] anns) + { + if (aa == null) + { + return null; + } + + StringBuilder msg = new StringBuilder(32); + if (aa.sequenceRef != null) + { + msg.append(aa.sequenceRef.getName()).append(" : "); + } + + if (aa.graphGroup == -1) + { + msg.append(aa.label); + } + else if (anns != null) + { + boolean first = true; + for (int i = anns.length - 1; i >= 0; i--) { - // TODO: we could refactor and merge this code with the code in - // jalview.gui.SeqPanel.mouseMoved(..) that formats sequence feature - // tooltips - desc.append(aa.getDescription(true).trim()); - // check to see if the description is an html fragment. - if (desc.length() < 6 || (desc.substring(0, 6).toLowerCase() - .indexOf("") < 0)) - { - // clean the description ready for embedding in html - desc = new StringBuffer(LEFT_ANGLE_BRACKET_PATTERN.matcher(desc) - .replaceAll("<")); - desc.insert(0, ""); - } - else + if (anns[i].graphGroup == aa.graphGroup) { - // remove terminating html if any - int i = desc.substring(desc.length() - 7).toLowerCase() - .lastIndexOf(""); - if (i > -1) + if (!first) { - desc.setLength(desc.length() - 7 + i); + msg.append(", "); } + msg.append(anns[i].label); + first = false; } - if (aa.hasScore()) - { - desc.append("
"); - } - // if (aa.hasProperties()) - // { - // desc.append(""); - // for (String prop : aa.getProperties()) - // { - // desc.append(""); - // } - // desc.append("
" + prop + "" - // + aa.getProperty(prop) + "
"); - // } } - else + } + + return msg.toString(); + } + + /** + * Answers a tooltip, formatted as html, containing the annotation description + * (prefixed by associated sequence id if applicable), and the annotation + * (non-positional) score if it has one. Answers null if neither description + * nor score is found. + * + * @param aa + * @return + */ + static String getTooltip(AlignmentAnnotation aa) + { + if (aa == null) + { + return null; + } + StringBuilder tooltip = new StringBuilder(); + if (aa.description != null && !aa.description.equals("New description")) + { + // TODO: we could refactor and merge this code with the code in + // jalview.gui.SeqPanel.mouseMoved(..) that formats sequence feature + // tooltips + String desc = aa.getDescription(true).trim(); + if (!desc.toLowerCase().startsWith(HTML_START_TAG)) { - // begin the tooltip's html fragment - desc.append(""); - if (aa.hasScore()) - { - // TODO: limit precision of score to avoid noise from imprecise - // doubles - // (64.7 becomes 64.7+/some tiny value). - desc.append(" Score: " + aa.score); - } + tooltip.append(HTML_START_TAG); + desc = desc.replace("<", "<"); } - if (desc.length() > 6) + else if (desc.toLowerCase().endsWith(HTML_END_TAG)) { - desc.append(""); - this.setToolTipText(desc.toString()); + desc = desc.substring(0, desc.length() - HTML_END_TAG.length()); } - else + tooltip.append(desc); + } + else + { + // begin the tooltip's html fragment + tooltip.append(HTML_START_TAG); + } + if (aa.hasScore()) + { + if (tooltip.length() > HTML_START_TAG.length()) { - this.setToolTipText(null); + tooltip.append("
"); } + // TODO: limit precision of score to avoid noise from imprecise + // doubles + // (64.7 becomes 64.7+/some tiny value). + tooltip.append(" Score: ").append(String.valueOf(aa.score)); + } + + if (tooltip.length() > HTML_START_TAG.length()) + { + return tooltip.append(HTML_END_TAG).toString(); } + + /* + * nothing in the tooltip (except "") + */ + return null; } /**