/*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
*/
package jalview.gui;
-import jalview.datamodel.Alignment;
-import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.Annotation;
-import jalview.datamodel.Sequence;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.io.FormatAdapter;
-import jalview.util.MessageManager;
-
import java.awt.Color;
+import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
-import java.awt.image.BufferedImage;
+import java.io.IOException;
import java.util.Arrays;
-import java.util.Vector;
-import java.util.regex.Pattern;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Locale;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
+import jalview.analysis.AlignSeq;
+import jalview.analysis.AlignmentUtils;
+import jalview.bin.Console;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.ContactMatrixI;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.FileFormat;
+import jalview.io.FormatAdapter;
+import jalview.io.NewickFile;
+import jalview.util.Comparison;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.ws.datamodel.alphafold.PAEContactMatrix;
+
/**
- * DOCUMENT ME!
- *
- * @author $author$
- * @version $Revision$
+ * The panel that holds the labels for alignment annotations, providing
+ * tooltips, context menus, drag to reorder rows, and drag to adjust panel
+ * height
*/
-public class AnnotationLabels extends JPanel implements MouseListener,
- MouseMotionListener, ActionListener
+public class AnnotationLabels extends JPanel
+ implements MouseListener, MouseMotionListener, ActionListener
{
- String TOGGLE_LABELSCALE = MessageManager.getString("label.scale_label_to_column");
+ private static final String HTML_END_TAG = "</html>";
- String ADDNEW = MessageManager.getString("label.add_new_row");
+ private static final String HTML_START_TAG = "<html>";
- String EDITNAME = MessageManager.getString("label.edit_label_description");
+ /**
+ * width in pixels within which height adjuster arrows are shown and active
+ */
+ private static final int HEIGHT_ADJUSTER_WIDTH = 50;
- String HIDE = MessageManager.getString("label.hide_row");
+ /**
+ * height in pixels for allowing height adjuster to be active
+ */
+ private static int HEIGHT_ADJUSTER_HEIGHT = 10;
- String DELETE = MessageManager.getString("label.delete_row");
+ private static final Font font = new Font("Arial", Font.PLAIN, 11);
- String SHOWALL = MessageManager.getString("label.show_all_hidden_rows");
+ private static final String TOGGLE_LABELSCALE = MessageManager
+ .getString("label.scale_label_to_column");
- String OUTPUT_TEXT = MessageManager.getString("label.export_annotation");
+ private static final String ADDNEW = MessageManager
+ .getString("label.add_new_row");
- String COPYCONS_SEQ = MessageManager.getString("label.copy_consensus_sequence");
+ private static final String EDITNAME = MessageManager
+ .getString("label.edit_label_description");
- boolean resizePanel = false;
+ private static final String HIDE = MessageManager
+ .getString("label.hide_row");
- Image image;
+ private static final String DELETE = MessageManager
+ .getString("label.delete_row");
- AlignmentPanel ap;
+ private static final String SHOWALL = MessageManager
+ .getString("label.show_all_hidden_rows");
- AlignViewport av;
+ private static final String OUTPUT_TEXT = MessageManager
+ .getString("label.export_annotation");
+
+ private static final String COPYCONS_SEQ = MessageManager
+ .getString("label.copy_consensus_sequence");
- boolean resizing = false;
+ private final boolean debugRedraw = false;
- MouseEvent dragEvent;
+ private AlignmentPanel ap;
- int oldY;
+ AlignViewport av;
- int selectedRow;
+ private MouseEvent dragEvent;
- int scrollOffset = 0;
+ private int oldY;
- Font font = new Font("Arial", Font.PLAIN, 11);
+ private int selectedRow;
+
+ private int scrollOffset = 0;
private boolean hasHiddenRows;
+ private boolean resizePanel = false;
+
/**
- * Creates a new AnnotationLabels object.
+ * Creates a new AnnotationLabels object
*
* @param ap
- * DOCUMENT ME!
*/
public AnnotationLabels(AlignmentPanel ap)
{
+
this.ap = ap;
av = ap.av;
ToolTipManager.sharedInstance().registerComponent(this);
- java.net.URL url = getClass().getResource("/images/idwidth.gif");
- Image temp = null;
-
- if (url != null)
- {
- temp = java.awt.Toolkit.getDefaultToolkit().createImage(url);
- }
-
- try
- {
- MediaTracker mt = new MediaTracker(this);
- mt.addImage(temp, 0);
- mt.waitForID(0);
- } catch (Exception ex)
- {
- }
-
- BufferedImage bi = new BufferedImage(temp.getHeight(this),
- temp.getWidth(this), BufferedImage.TYPE_INT_RGB);
- Graphics2D g = (Graphics2D) bi.getGraphics();
- g.rotate(Math.toRadians(90));
- g.drawImage(temp, 0, -bi.getWidth(this), this);
- image = bi;
-
addMouseListener(this);
addMouseMotionListener(this);
- addMouseWheelListener(ap.annotationPanel);
+ addMouseWheelListener(ap.getAnnotationPanel());
}
public AnnotationLabels(AlignViewport av)
* @param evt
* DOCUMENT ME!
*/
+ @Override
public void actionPerformed(ActionEvent evt)
{
AlignmentAnnotation[] aa = ap.av.getAlignment()
.getAlignmentAnnotation();
- if (evt.getActionCommand().equals(ADDNEW))
+ String action = evt.getActionCommand();
+ if (ADDNEW.equals(action))
{
+ /*
+ * non-returning dialog
+ */
AlignmentAnnotation newAnnotation = new AlignmentAnnotation(null,
null, new Annotation[ap.av.getAlignment().getWidth()]);
-
- if (!editLabelDescription(newAnnotation))
- {
- return;
- }
-
- ap.av.getAlignment().addAnnotation(newAnnotation);
- ap.av.getAlignment().setAnnotationIndex(newAnnotation, 0);
+ editLabelDescription(newAnnotation, true);
}
- else if (evt.getActionCommand().equals(EDITNAME))
+ else if (EDITNAME.equals(action))
{
- editLabelDescription(aa[selectedRow]);
- repaint();
+ /*
+ * non-returning dialog
+ */
+ editLabelDescription(aa[selectedRow], false);
}
- else if (evt.getActionCommand().equals(HIDE))
+ else if (HIDE.equals(action))
{
aa[selectedRow].visible = false;
}
- else if (evt.getActionCommand().equals(DELETE))
+ else if (DELETE.equals(action))
{
ap.av.getAlignment().deleteAnnotation(aa[selectedRow]);
+ ap.av.getCalcManager().removeWorkerForAnnotation(aa[selectedRow]);
}
- else if (evt.getActionCommand().equals(SHOWALL))
+ else if (SHOWALL.equals(action))
{
for (int i = 0; i < aa.length; i++)
{
}
}
}
- else if (evt.getActionCommand().equals(OUTPUT_TEXT))
+ else if (OUTPUT_TEXT.equals(action))
{
- new AnnotationExporter().exportAnnotations(ap,
- new AlignmentAnnotation[]
- { aa[selectedRow] }, null, null);
+ new AnnotationExporter(ap).exportAnnotation(aa[selectedRow]);
}
- else if (evt.getActionCommand().equals(COPYCONS_SEQ))
+ else if (COPYCONS_SEQ.equals(action))
{
SequenceI cons = null;
if (aa[selectedRow].groupRef != null)
{
copy_annotseqtoclipboard(cons);
}
-
}
- else if (evt.getActionCommand().equals(TOGGLE_LABELSCALE))
+ else if (TOGGLE_LABELSCALE.equals(action))
{
aa[selectedRow].scaleColLabel = !aa[selectedRow].scaleColLabel;
}
- refresh();
-
+ ap.refresh(true);
}
/**
- * Redraw sensibly.
+ * Shows a dialog where the annotation name and description may be edited. If
+ * parameter addNew is true, then on confirmation, a new AlignmentAnnotation
+ * is added, else an existing annotation is updated.
+ *
+ * @param annotation
+ * @param addNew
*/
- protected void refresh()
+ void editLabelDescription(AlignmentAnnotation annotation, boolean addNew)
+ {
+ String name = MessageManager.getString("label.annotation_name");
+ String description = MessageManager
+ .getString("label.annotation_description");
+ String title = MessageManager
+ .getString("label.edit_annotation_name_description");
+ EditNameDialog dialog = new EditNameDialog(annotation.label,
+ annotation.description, name, description);
+
+ dialog.showDialog(ap.alignFrame, title, () -> {
+ annotation.label = dialog.getName();
+ String text = dialog.getDescription();
+ if (text != null && text.length() == 0)
+ {
+ text = null;
+ }
+ annotation.description = text;
+ if (addNew)
+ {
+ ap.av.getAlignment().addAnnotation(annotation);
+ ap.av.getAlignment().setAnnotationIndex(annotation, 0);
+ }
+ ap.refresh(true);
+ return null;
+ });
+ }
+
+ @Override
+ public void mousePressed(MouseEvent evt)
{
- ap.validateAnnotationDimensions(false);
- ap.addNotify();
- ap.repaint();
+ getSelectedRow(evt.getY() - getScrollOffset());
+ oldY = evt.getY();
+ if (evt.isPopupTrigger())
+ {
+ showPopupMenu(evt);
+ }
}
/**
- * DOCUMENT ME!
+ * Build and show the Pop-up menu at the right-click mouse position
*
- * @param e
- * DOCUMENT ME!
+ * @param evt
*/
- boolean editLabelDescription(AlignmentAnnotation annotation)
+ void showPopupMenu(MouseEvent evt)
{
- EditNameDialog dialog = new EditNameDialog(annotation.label,
- annotation.description, " Annotation Name ",
- "Annotation Description ", "Edit Annotation Name/Description",
- ap.alignFrame);
+ evt.consume();
+ final AlignmentAnnotation[] aa = ap.av.getAlignment()
+ .getAlignmentAnnotation();
- if (!dialog.accept)
+ JPopupMenu pop = new JPopupMenu(
+ MessageManager.getString("label.annotations"));
+ JMenuItem item = new JMenuItem(ADDNEW);
+ item.addActionListener(this);
+ pop.add(item);
+ if (selectedRow < 0)
{
- return false;
+ if (hasHiddenRows)
+ { // let the user make everything visible again
+ item = new JMenuItem(SHOWALL);
+ item.addActionListener(this);
+ pop.add(item);
+ }
+ pop.show(this, evt.getX(), evt.getY());
+ return;
}
-
- annotation.label = dialog.getName();
-
- String text = dialog.getDescription();
- if (text != null && text.length() == 0)
+ item = new JMenuItem(EDITNAME);
+ item.addActionListener(this);
+ pop.add(item);
+ item = new JMenuItem(HIDE);
+ item.addActionListener(this);
+ pop.add(item);
+ // JAL-1264 hide all sequence-specific annotations of this type
+ if (selectedRow < aa.length)
{
- text = null;
+ if (aa[selectedRow].sequenceRef != null)
+ {
+ final String label = aa[selectedRow].label;
+ JMenuItem hideType = new JMenuItem();
+ String text = MessageManager.getString("label.hide_all") + " "
+ + label;
+ hideType.setText(text);
+ hideType.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ AlignmentUtils.showOrHideSequenceAnnotations(
+ ap.av.getAlignment(), Collections.singleton(label),
+ null, false, false);
+ ap.refresh(true);
+ }
+ });
+ pop.add(hideType);
+ }
}
- annotation.description = text;
+ item = new JMenuItem(DELETE);
+ item.addActionListener(this);
+ pop.add(item);
+ if (hasHiddenRows)
+ {
+ item = new JMenuItem(SHOWALL);
+ item.addActionListener(this);
+ pop.add(item);
+ }
+ item = new JMenuItem(OUTPUT_TEXT);
+ item.addActionListener(this);
+ pop.add(item);
+ // TODO: annotation object should be typed for autocalculated/derived
+ // property methods
+ if (selectedRow < aa.length)
+ {
+ final String label = aa[selectedRow].label;
+ if (!aa[selectedRow].autoCalculated)
+ {
+ 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,
+ aa[selectedRow].scaleColLabel);
+ item.addActionListener(this);
+ pop.add(item);
+ }
+ }
+ else if (label.indexOf("Consensus") > -1)
+ {
+ addConsensusMenuOptions(ap, aa[selectedRow], pop);
- return true;
+ final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ);
+ consclipbrd.addActionListener(this);
+ pop.add(consclipbrd);
+ }
+ if (aa[selectedRow].graph == AlignmentAnnotation.CONTACT_MAP
+ && PAEContactMatrix.PAEMATRIX
+ .equals(aa[selectedRow].getCalcId()))
+ {
+ final PAEContactMatrix cm = (PAEContactMatrix) av
+ .getContactMatrix(aa[selectedRow]);
+ if (cm!=null && cm.getNewick()!=null && cm.getNewick().length()>0)
+ {
+ item = new JMenuItem("Show Tree for Matrix");
+ item.addActionListener(new ActionListener()
+ {
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+
+ ap.alignFrame.showContactMapTree(aa[selectedRow],cm);
+
+ }
+ });
+ pop.addSeparator();
+ pop.add(item);
+ }
+
+ }
+ }
+ pop.show(this, evt.getX(), evt.getY());
}
/**
- * DOCUMENT ME!
+ * 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 evt
- * DOCUMENT ME!
+ * @param ap
+ * @param ann
+ * @param pop
*/
- public void mousePressed(MouseEvent evt)
+ static void addConsensusMenuOptions(AlignmentPanel ap,
+ AlignmentAnnotation ann, JPopupMenu pop)
{
- getSelectedRow(evt.getY() - scrollOffset);
- oldY = evt.getY();
+ pop.addSeparator();
+
+ final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
+ MessageManager.getString("label.ignore_gaps_consensus"),
+ (ann.groupRef != null) ? ann.groupRef.getIgnoreGapsConsensus()
+ : ap.av.isIgnoreGapsConsensus());
+ final AlignmentAnnotation aaa = ann;
+ cbmi.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ if (aaa.groupRef != null)
+ {
+ aaa.groupRef.setIgnoreGapsConsensus(cbmi.getState());
+ ap.getAnnotationPanel()
+ .paint(ap.getAnnotationPanel().getGraphics());
+ }
+ else
+ {
+ ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
+ }
+ ap.alignmentChanged();
+ }
+ });
+ pop.add(cbmi);
+
+ if (aaa.groupRef != null)
+ {
+ /*
+ * group consensus options
+ */
+ final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
+ MessageManager.getString("label.show_group_histogram"),
+ ann.groupRef.isShowConsensusHistogram());
+ chist.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ aaa.groupRef.setShowConsensusHistogram(chist.getState());
+ ap.repaint();
+ }
+ });
+ pop.add(chist);
+ final JCheckBoxMenuItem cprofl = new JCheckBoxMenuItem(
+ MessageManager.getString("label.show_group_logo"),
+ ann.groupRef.isShowSequenceLogo());
+ cprofl.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ aaa.groupRef.setshowSequenceLogo(cprofl.getState());
+ ap.repaint();
+ }
+ });
+ pop.add(cprofl);
+ final JCheckBoxMenuItem cproflnorm = new JCheckBoxMenuItem(
+ MessageManager.getString("label.normalise_group_logo"),
+ ann.groupRef.isNormaliseSequenceLogo());
+ cproflnorm.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ aaa.groupRef.setNormaliseSequenceLogo(cproflnorm.getState());
+ // automatically enable logo display if we're clicked
+ aaa.groupRef.setshowSequenceLogo(true);
+ ap.repaint();
+ }
+ });
+ pop.add(cproflnorm);
+ }
+ else
+ {
+ /*
+ * alignment consensus options
+ */
+ final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
+ MessageManager.getString("label.show_histogram"),
+ ap.av.isShowConsensusHistogram());
+ chist.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ ap.av.setShowConsensusHistogram(chist.getState());
+ ap.alignFrame.setMenusForViewport();
+ ap.repaint();
+ }
+ });
+ pop.add(chist);
+ final JCheckBoxMenuItem cprof = new JCheckBoxMenuItem(
+ MessageManager.getString("label.show_logo"),
+ ap.av.isShowSequenceLogo());
+ cprof.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ ap.av.setShowSequenceLogo(cprof.getState());
+ ap.alignFrame.setMenusForViewport();
+ ap.repaint();
+ }
+ });
+ pop.add(cprof);
+ final JCheckBoxMenuItem cprofnorm = new JCheckBoxMenuItem(
+ MessageManager.getString("label.normalise_logo"),
+ ap.av.isNormaliseSequenceLogo());
+ cprofnorm.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ ap.av.setShowSequenceLogo(true);
+ ap.av.setNormaliseSequenceLogo(cprofnorm.getState());
+ ap.alignFrame.setMenusForViewport();
+ ap.repaint();
+ }
+ });
+ pop.add(cprofnorm);
+ }
}
/**
- * DOCUMENT ME!
+ * Reorders annotation rows after a drag of a label
*
* @param evt
- * DOCUMENT ME!
*/
+ @Override
public void mouseReleased(MouseEvent evt)
{
+ if (evt.isPopupTrigger())
+ {
+ showPopupMenu(evt);
+ return;
+ }
+
int start = selectedRow;
- getSelectedRow(evt.getY() - scrollOffset);
+ getSelectedRow(evt.getY() - getScrollOffset());
int end = selectedRow;
+ /*
+ * if dragging to resize instead, start == end
+ */
if (start != end)
{
// Swap these annotations
resizePanel = false;
dragEvent = null;
repaint();
- ap.annotationPanel.repaint();
+ ap.getAnnotationPanel().repaint();
}
/**
- * DOCUMENT ME!
- *
- * @param evt
- * DOCUMENT ME!
- */
- public void mouseEntered(MouseEvent evt)
- {
- if (evt.getY() < 10)
- {
- resizePanel = true;
- repaint();
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param evt
- * DOCUMENT ME!
+ * Removes the height adjuster image on leaving the panel, unless currently
+ * dragging it
*/
+ @Override
public void mouseExited(MouseEvent evt)
{
- if (dragEvent == null)
+ if (resizePanel && dragEvent == null)
{
resizePanel = false;
repaint();
}
/**
- * DOCUMENT ME!
+ * A mouse drag may be either an adjustment of the panel height (if flag
+ * resizePanel is set on), or a reordering of the annotation rows. The former
+ * is dealt with by this method, the latter in mouseReleased.
*
* @param evt
- * DOCUMENT ME!
*/
+ @Override
public void mouseDragged(MouseEvent evt)
{
dragEvent = evt;
Dimension d = ap.annotationScroller.getPreferredSize();
int dif = evt.getY() - oldY;
- dif /= ap.av.charHeight;
- dif *= ap.av.charHeight;
+ dif /= ap.av.getCharHeight();
+ dif *= ap.av.getCharHeight();
if ((d.height - dif) > 20)
{
- ap.annotationScroller.setPreferredSize(new Dimension(d.width,
- d.height - dif));
+ ap.annotationScroller
+ .setPreferredSize(new Dimension(d.width, d.height - dif));
d = ap.annotationSpaceFillerHolder.getPreferredSize();
- ap.annotationSpaceFillerHolder.setPreferredSize(new Dimension(
- d.width, d.height - dif));
- ap.paintAlignment(true);
+ ap.annotationSpaceFillerHolder
+ .setPreferredSize(new Dimension(d.width, d.height - dif));
+ ap.paintAlignment(true, false);
}
ap.addNotify();
}
/**
- * DOCUMENT ME!
+ * Updates the tooltip as the mouse moves over the labels
*
* @param evt
- * DOCUMENT ME!
*/
+ @Override
public void mouseMoved(MouseEvent evt)
{
- resizePanel = evt.getY() < 10;
+ showOrHideAdjuster(evt);
- getSelectedRow(evt.getY() - scrollOffset);
+ getSelectedRow(evt.getY() - getScrollOffset());
- if (selectedRow > -1
- && ap.av.getAlignment().getAlignmentAnnotation().length > selectedRow)
+ 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);
+ }
+ }
+
+ /**
+ * 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(" : ");
+ }
- StringBuffer desc = new StringBuffer();
- if (aa.description != null
- && !aa.description.equals("New description"))
+ 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("<html>") < 0))
+ if (anns[i].graphGroup == aa.graphGroup)
{
- // clean the description ready for embedding in html
- desc = new StringBuffer(Pattern.compile("<").matcher(desc)
- .replaceAll("<"));
- desc.insert(0, "<html>");
- }
- else
- {
- // remove terminating html if any
- int i = desc.substring(desc.length() - 7).toLowerCase()
- .lastIndexOf("</html>");
- 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("<br/>");
- }
- // if (aa.hasProperties())
- // {
- // desc.append("<table>");
- // for (String prop : aa.getProperties())
- // {
- // desc.append("<tr><td>" + prop + "</td><td>"
- // + aa.getProperty(prop) + "</td><tr>");
- // }
- // desc.append("</table>");
- // }
}
- 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(Locale.ROOT).startsWith(HTML_START_TAG))
{
- // begin the tooltip's html fragment
- desc.append("<html>");
- 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(Locale.ROOT).endsWith(HTML_END_TAG))
{
- desc.append("</html>");
- 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("<br/>");
}
+ // 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 "<html>")
+ */
+ return null;
}
/**
- * DOCUMENT ME!
+ * Shows the height adjuster image if the mouse moves into the top left
+ * region, or hides it if the mouse leaves the regio
*
* @param evt
- * DOCUMENT ME!
*/
+ protected void showOrHideAdjuster(MouseEvent evt)
+ {
+ boolean was = resizePanel;
+ resizePanel = evt.getY() < HEIGHT_ADJUSTER_HEIGHT
+ && evt.getX() < HEIGHT_ADJUSTER_WIDTH;
+
+ if (resizePanel != was)
+ {
+ setCursor(Cursor
+ .getPredefinedCursor(resizePanel ? Cursor.S_RESIZE_CURSOR
+ : Cursor.DEFAULT_CURSOR));
+ repaint();
+ }
+ }
+
+ @Override
public void mouseClicked(MouseEvent evt)
{
final AlignmentAnnotation[] aa = ap.av.getAlignment()
.getAlignmentAnnotation();
- if (SwingUtilities.isLeftMouseButton(evt))
+ if (!evt.isPopupTrigger() && SwingUtilities.isLeftMouseButton(evt))
{
if (selectedRow > -1 && selectedRow < aa.length)
{
{
// todo: make the ap scroll to the selection - not necessary, first
// click highlights/scrolls, second selects
- ap.seqPanel.ap.idPanel.highlightSearchResults(null);
- ap.av.setSelectionGroup(// new SequenceGroup(
- aa[selectedRow].groupRef); // );
- ap.paintAlignment(false);
+ ap.getSeqPanel().ap.getIdPanel().highlightSearchResults(null);
+ // process modifiers
+ SequenceGroup sg = ap.av.getSelectionGroup();
+ if (sg == null || sg == aa[selectedRow].groupRef
+ || !(Platform.isControlDown(evt) || evt.isShiftDown()))
+ {
+ if (Platform.isControlDown(evt) || evt.isShiftDown())
+ {
+ // clone a new selection group from the associated group
+ ap.av.setSelectionGroup(
+ new SequenceGroup(aa[selectedRow].groupRef));
+ }
+ else
+ {
+ // set selection to the associated group so it can be edited
+ ap.av.setSelectionGroup(aa[selectedRow].groupRef);
+ }
+ }
+ else
+ {
+ // modify current selection with associated group
+ int remainToAdd = aa[selectedRow].groupRef.getSize();
+ for (SequenceI sgs : aa[selectedRow].groupRef.getSequences())
+ {
+ if (jalview.util.Platform.isControlDown(evt))
+ {
+ sg.addOrRemove(sgs, --remainToAdd == 0);
+ }
+ else
+ {
+ // notionally, we should also add intermediate sequences from
+ // last added sequence ?
+ sg.addSequence(sgs, --remainToAdd == 0);
+ }
+ }
+ }
+
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
else
{
- ap.seqPanel.ap.idPanel
- .highlightSearchResults(aa[selectedRow].groupRef
- .getSequences(null));
+ ap.getSeqPanel().ap.getIdPanel().highlightSearchResults(
+ aa[selectedRow].groupRef.getSequences(null));
}
return;
}
{
if (evt.getClickCount() == 1)
{
- ap.seqPanel.ap.idPanel.highlightSearchResults(Arrays
- .asList(new SequenceI[]
+ ap.getSeqPanel().ap.getIdPanel()
+ .highlightSearchResults(Arrays.asList(new SequenceI[]
{ aa[selectedRow].sequenceRef }));
}
else if (evt.getClickCount() >= 2)
{
- ap.seqPanel.ap.idPanel.highlightSearchResults(null);
+ ap.getSeqPanel().ap.getIdPanel().highlightSearchResults(null);
SequenceGroup sg = ap.av.getSelectionGroup();
- if (sg!=null)
+ if (sg != null)
{
- // we make a copy rather than edit the current selection if no modifiers pressed
+ // we make a copy rather than edit the current selection if no
+ // modifiers pressed
// see Enhancement JAL-1557
- if (!(evt.isControlDown() || evt.isShiftDown()))
+ if (!(Platform.isControlDown(evt) || evt.isShiftDown()))
{
sg = new SequenceGroup(sg);
sg.clear();
sg.addSequence(aa[selectedRow].sequenceRef, false);
- } else {
- if (evt.isControlDown())
+ }
+ else
+ {
+ if (Platform.isControlDown(evt))
{
sg.addOrRemove(aa[selectedRow].sequenceRef, true);
- } else {
- // notionally, we should also add intermediate sequences from last added sequence ?
+ }
+ else
+ {
+ // notionally, we should also add intermediate sequences from
+ // last added sequence ?
sg.addSequence(aa[selectedRow].sequenceRef, true);
}
}
- } else {
+ }
+ else
+ {
sg = new SequenceGroup();
sg.setStartRes(0);
- sg.setEndRes(ap.av.getAlignment().getWidth()-1);
+ sg.setEndRes(ap.av.getAlignment().getWidth() - 1);
sg.addSequence(aa[selectedRow].sequenceRef, false);
}
ap.av.setSelectionGroup(sg);
- ap.av.sendSelection();
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
+ ap.av.sendSelection();
}
}
}
- }
- if (!SwingUtilities.isRightMouseButton(evt))
- {
- return;
- }
-
- JPopupMenu pop = new JPopupMenu(
- MessageManager.getString("label.annotations"));
- JMenuItem item = new JMenuItem(ADDNEW);
- item.addActionListener(this);
- pop.add(item);
- if (selectedRow < 0)
- {
- if (hasHiddenRows)
- { // let the user make everything visible again
- item = new JMenuItem(SHOWALL);
- item.addActionListener(this);
- pop.add(item);
- }
- pop.show(this, evt.getX(), evt.getY());
return;
}
- item = new JMenuItem(EDITNAME);
- item.addActionListener(this);
- pop.add(item);
- item = new JMenuItem(HIDE);
- item.addActionListener(this);
- pop.add(item);
- // JAL-1264 hide all sequence-specific annotations of this type
- final String label = aa[selectedRow].label;
- if (selectedRow < aa.length)
- {
- if (aa[selectedRow].sequenceRef != null)
- {
- JMenuItem hideType = new JMenuItem();
- String text = MessageManager.getString("label.hide_all") + " " + label;
- hideType.setText(text);
- hideType.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- for (AlignmentAnnotation ann : ap.av.getAlignment()
- .getAlignmentAnnotation())
- {
- if (ann.sequenceRef != null && ann.label != null
- && ann.label.equals(label))
- {
- ann.visible = false;
- }
- }
- refresh();
- }
- });
- pop.add(hideType);
- }
- }
- item = new JMenuItem(DELETE);
- item.addActionListener(this);
- pop.add(item);
- if (hasHiddenRows)
- {
- item = new JMenuItem(SHOWALL);
- item.addActionListener(this);
- pop.add(item);
- }
- item = new JMenuItem(OUTPUT_TEXT);
- item.addActionListener(this);
- pop.add(item);
- // TODO: annotation object should be typed for autocalculated/derived
- // property methods
- if (selectedRow < aa.length)
- {
- if (!aa[selectedRow].autoCalculated)
- {
- 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,
- aa[selectedRow].scaleColLabel);
- item.addActionListener(this);
- pop.add(item);
- }
- }
- else if (label.indexOf("Consensus") > -1)
- {
- pop.addSeparator();
- // av and sequencegroup need to implement same interface for
- final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
- MessageManager.getString("label.ignore_gaps_consensus"),
- (aa[selectedRow].groupRef != null) ? aa[selectedRow].groupRef
- .getIgnoreGapsConsensus() : ap.av
- .getIgnoreGapsConsensus());
- final AlignmentAnnotation aaa = aa[selectedRow];
- cbmi.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- if (aaa.groupRef != null)
- {
- // TODO: pass on reference to ap so the view can be updated.
- aaa.groupRef.setIgnoreGapsConsensus(cbmi.getState());
- ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
- }
- else
- {
- ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
- }
- }
- });
- pop.add(cbmi);
- // av and sequencegroup need to implement same interface for
- if (aaa.groupRef != null)
- {
- final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
- MessageManager.getString("label.show_group_histogram"),
- aa[selectedRow].groupRef.isShowConsensusHistogram());
- chist.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // TODO: pass on reference
- // to ap
- // so the
- // view
- // can be
- // updated.
- aaa.groupRef.setShowConsensusHistogram(chist.getState());
- ap.repaint();
- // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
- }
- });
- pop.add(chist);
- final JCheckBoxMenuItem cprofl = new JCheckBoxMenuItem(
- MessageManager.getString("label.show_group_logo"),
- aa[selectedRow].groupRef.isShowSequenceLogo());
- cprofl.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // TODO: pass on reference
- // to ap
- // so the
- // view
- // can be
- // updated.
- aaa.groupRef.setshowSequenceLogo(cprofl.getState());
- ap.repaint();
- // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
- }
- });
- pop.add(cprofl);
- final JCheckBoxMenuItem cproflnorm = new JCheckBoxMenuItem(
- MessageManager.getString("label.normalise_group_logo"),
- aa[selectedRow].groupRef.isNormaliseSequenceLogo());
- cproflnorm.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
-
- // TODO: pass on reference
- // to ap
- // so the
- // view
- // can be
- // updated.
- aaa.groupRef.setNormaliseSequenceLogo(cproflnorm.getState());
- // automatically enable logo display if we're clicked
- aaa.groupRef.setshowSequenceLogo(true);
- ap.repaint();
- // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
- }
- });
- pop.add(cproflnorm);
- }
- else
- {
- final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
- MessageManager.getString("label.show_histogram"), av.isShowConsensusHistogram());
- chist.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // TODO: pass on reference
- // to ap
- // so the
- // view
- // can be
- // updated.
- av.setShowConsensusHistogram(chist.getState());
- ap.alignFrame.setMenusForViewport();
- ap.repaint();
- // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
- }
- });
- pop.add(chist);
- final JCheckBoxMenuItem cprof = new JCheckBoxMenuItem(
- MessageManager.getString("label.show_logo"), av.isShowSequenceLogo());
- cprof.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // TODO: pass on reference
- // to ap
- // so the
- // view
- // can be
- // updated.
- av.setShowSequenceLogo(cprof.getState());
- ap.alignFrame.setMenusForViewport();
- ap.repaint();
- // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
- }
- });
- pop.add(cprof);
- final JCheckBoxMenuItem cprofnorm = new JCheckBoxMenuItem(
- MessageManager.getString("label.normalise_logo"), av.isNormaliseSequenceLogo());
- cprofnorm.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- // TODO: pass on reference
- // to ap
- // so the
- // view
- // can be
- // updated.
- av.setShowSequenceLogo(true);
- av.setNormaliseSequenceLogo(cprofnorm.getState());
- ap.alignFrame.setMenusForViewport();
- ap.repaint();
- // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
- }
- });
- pop.add(cprofnorm);
- }
- final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ);
- consclipbrd.addActionListener(this);
- pop.add(consclipbrd);
- }
- }
- pop.show(this, evt.getX(), evt.getY());
}
/**
*/
protected void copy_annotseqtoclipboard(SequenceI sq)
{
- SequenceI[] seqs = new SequenceI[]
- { sq };
+ SequenceI[] seqs = new SequenceI[] { sq };
String[] omitHidden = null;
- SequenceI[] dseqs = new SequenceI[]
- { sq.getDatasetSequence() };
+ SequenceI[] dseqs = new SequenceI[] { sq.getDatasetSequence() };
if (dseqs[0] == null)
{
dseqs[0] = new Sequence(sq);
- dseqs[0].setSequence(jalview.analysis.AlignSeq.extractGaps(
- jalview.util.Comparison.GapChars, sq.getSequenceAsString()));
+ dseqs[0].setSequence(AlignSeq.extractGaps(Comparison.GapChars,
+ sq.getSequenceAsString()));
sq.setDatasetSequence(dseqs[0]);
}
Alignment ds = new Alignment(dseqs);
if (av.hasHiddenColumns())
{
- omitHidden = av.getColumnSelection().getVisibleSequenceStrings(0,
- sq.getLength(), seqs);
+ Iterator<int[]> it = av.getAlignment().getHiddenColumns()
+ .getVisContigsIterator(0, sq.getLength(), false);
+ omitHidden = new String[] { sq.getSequenceStringFromIterator(it) };
}
- String output = new FormatAdapter().formatSequences("Fasta", seqs,
- omitHidden);
+ int[] alignmentStartEnd = new int[] { 0, ds.getWidth() - 1 };
+ if (av.hasHiddenColumns())
+ {
+ alignmentStartEnd = av.getAlignment().getHiddenColumns()
+ .getVisibleStartAndEndIndex(av.getAlignment().getWidth());
+ }
+
+ String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
+ seqs, omitHidden, alignmentStartEnd);
Toolkit.getDefaultToolkit().getSystemClipboard()
.setContents(new StringSelection(output), Desktop.instance);
- Vector hiddenColumns = null;
+ HiddenColumns hiddenColumns = null;
+
if (av.hasHiddenColumns())
{
- hiddenColumns = new Vector();
- for (int i = 0; i < av.getColumnSelection().getHiddenColumns().size(); i++)
- {
- int[] region = (int[]) av.getColumnSelection().getHiddenColumns()
- .elementAt(i);
-
- hiddenColumns.addElement(new int[]
- { region[0], region[1] });
- }
+ hiddenColumns = new HiddenColumns(
+ av.getAlignment().getHiddenColumns());
}
- Desktop.jalviewClipboard = new Object[]
- { seqs, ds, // what is the dataset of a consensus sequence ? need to flag
+ Desktop.jalviewClipboard = new Object[] { seqs, ds, // what is the dataset
+ // of a consensus
+ // sequence ? need to
+ // flag
// sequence as special.
hiddenColumns };
}
* @param g1
* DOCUMENT ME!
*/
+ @Override
public void paintComponent(Graphics g)
{
int width = getWidth();
if (width == 0)
{
- width = ap.calculateIdWidth().width + 4;
+ width = ap.calculateIdWidth().width;
}
Graphics2D g2 = (Graphics2D) g;
drawComponent(g, false, width);
}
- private final boolean debugRedraw = false;
-
/**
* Draw the full set of annotation Labels for the alignment at the given
* cursor
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
- g.translate(0, scrollOffset);
+ g.translate(0, getScrollOffset());
g.setColor(Color.black);
-
+ SequenceI lastSeqRef = null;
+ String lastLabel = null;
AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
int fontHeight = g.getFont().getSize();
int y = 0;
int ofontH = fontHeight;
int sOffset = 0;
int visHeight = 0;
- int[] visr = (ap != null && ap.annotationPanel != null) ? ap.annotationPanel
- .getVisibleVRange() : null;
+ int[] visr = (ap != null && ap.getAnnotationPanel() != null)
+ ? ap.getAnnotationPanel().getVisibleVRange()
+ : null;
if (clip && visr != null)
{
sOffset = visr[0];
{
hasHiddenRows = false;
int olY = 0;
+ int nexAA = 0;
for (int i = 0; i < aa.length; i++)
{
visible = true;
continue;
}
olY = y;
+ // look ahead to next annotation
+ for (nexAA=i+1; nexAA<aa.length && !aa[nexAA].visible; nexAA++)
+ ;
y += aa[i].height;
if (clip)
{
{
if (debugRedraw)
{
- System.out.println("Scroll offset: " + sOffset
- + " after vis: " + i);
+ System.out.println(
+ "Scroll offset: " + sOffset + " after vis: " + i);
}
after = true;
}
{
offset += fm.getDescent();
}
-
- x = width - fm.stringWidth(aa[i].label) - 3;
+ String label = aa[i].label;
+ boolean vertBar = false;
+ if ((lastLabel != null && lastLabel.equals(label)))
+ {
+ label = aa[i].description;
+ }
+ else
+ {
+ if (nexAA < aa.length && label.equals(aa[nexAA].label)) // &&
+ // aa[nexY].sequenceRef==aa[i].sequenceRef)
+ {
+ lastLabel = label;
+ // next label is the same as this label
+ label = aa[i].description;
+ }
+ else
+ {
+ lastLabel = label;
+ }
+ }
+ if (aa[i].sequenceRef != null)
+ {
+ if (aa[i].sequenceRef != lastSeqRef)
+ {
+ label = aa[i].sequenceRef.getName() + " " + label;
+ // TODO record relationship between sequence and this annotation and
+ // display it here
+ }
+ else
+ {
+ vertBar = true;
+ }
+ }
+ x = width - fm.stringWidth(label) - 3;
if (aa[i].graphGroup > -1)
{
}
if (groupSize * (fontHeight + 8) < aa[i].height)
{
- graphExtras = (aa[i].height - (groupSize * (fontHeight + 8))) / 2;
+ graphExtras = (aa[i].height - (groupSize * (fontHeight + 8)))
+ / 2;
}
else
{
{
fontHeight = -8 + (int) h;
s = ((float) fontHeight) / (float) ofontH;
- Font f = baseFont.deriveFont(AffineTransform
- .getScaleInstance(s, s));
+ Font f = baseFont
+ .deriveFont(AffineTransform.getScaleInstance(s, s));
g.setFont(f);
fm = g.getFontMetrics();
- graphExtras = (aa[i].height - (groupSize * (fontHeight + 8))) / 2;
+ graphExtras = (aa[i].height - (groupSize * (fontHeight + 8)))
+ / 2;
}
}
if (visible)
g.setColor(aa[gg]._linecolour);
g.drawLine(x, y - graphExtras + 3,
- x + fm.stringWidth(aa[gg].label), y - graphExtras
- + 3);
+ x + fm.stringWidth(aa[gg].label),
+ y - graphExtras + 3);
}
g.setColor(Color.black);
}
else
{
- g.drawString(aa[i].label, x, y + offset);
+ if (vertBar)
+ {
+ g.drawLine(width-3, y + offset-fontHeight, width-3, (int)(y - 1.5*aa[i].height-offset-fontHeight));
+ // g.drawLine(20, y + offset, x - 20, y + offset);
+
+ }
+ g.drawString(label, x, y + offset);
}
+ lastSeqRef = aa[i].sequenceRef;
}
}
- if (resizePanel)
- {
- g.drawImage(image, 2, 0 - scrollOffset, this);
- }
- else if (dragEvent != null && aa != null)
+ if (!resizePanel && dragEvent != null && aa != null)
{
g.setColor(Color.lightGray);
- g.drawString(aa[selectedRow].label, dragEvent.getX(),
- dragEvent.getY() - scrollOffset);
+ g.drawString(
+ (aa[selectedRow].sequenceRef == null ? ""
+ : aa[selectedRow].sequenceRef.getName())
+ + aa[selectedRow].label,
+ dragEvent.getX(), dragEvent.getY() - getScrollOffset());
}
- if (!av.wrapAlignment && ((aa == null) || (aa.length < 1)))
+ if (!av.getWrapAlignment() && ((aa == null) || (aa.length < 1)))
{
g.drawString(MessageManager.getString("label.right_click"), 2, 8);
g.drawString(MessageManager.getString("label.to_add_annotation"), 2,
18);
}
}
+
+ public int getScrollOffset()
+ {
+ return scrollOffset;
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e)
+ {
+ }
}