/*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
- * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
- *
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.1)
+ * Copyright (C) 2014 The Jalview Authors
+ *
* This file is part of Jalview.
- *
+ *
* Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
+ * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.gui;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
+
import javax.swing.*;
import jalview.datamodel.*;
import jalview.renderer.AnnotationRenderer;
import jalview.renderer.AwtRenderPanelI;
+import jalview.util.MessageManager;
/**
- * AnnotationPanel displays visible portion of annotation rows below unwrapped alignment
+ * AnnotationPanel displays visible portion of annotation rows below unwrapped
+ * alignment
+ *
* @author $author$
* @version $Revision$
*/
public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
- MouseListener, MouseMotionListener, ActionListener,
- AdjustmentListener
+ MouseListener, MouseWheelListener, MouseMotionListener,
+ ActionListener, AdjustmentListener, Scrollable
{
final String HELIX = "Helix";
public final AnnotationRenderer renderer;
+ private MouseWheelListener[] _mwl;
+
/**
* Creates a new AnnotationPanel object.
- *
+ *
* @param ap
* DOCUMENT ME!
*/
addMouseMotionListener(this);
ap.annotationScroller.getVerticalScrollBar()
.addAdjustmentListener(this);
+ // save any wheel listeners on the scroller, so we can propagate scroll
+ // events to them.
+ _mwl = ap.annotationScroller.getMouseWheelListeners();
+ // and then set our own listener to consume all mousewheel events
+ ap.annotationScroller.addMouseWheelListener(this);
renderer = new AnnotationRenderer();
}
renderer = new AnnotationRenderer();
}
- /**
- * DOCUMENT ME!
- *
- * @param evt
- * DOCUMENT ME!
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent e)
+ {
+ if (e.isShiftDown())
+ {
+ e.consume();
+ if (e.getWheelRotation() > 0)
+ {
+ ap.scrollRight(true);
+ }
+ else
+ {
+ ap.scrollRight(false);
+ }
+ }
+ else
+ {
+ // TODO: find the correct way to let the event bubble up to
+ // ap.annotationScroller
+ for (MouseWheelListener mwl : _mwl)
+ {
+ if (mwl != null)
+ {
+ mwl.mouseWheelMoved(e);
+ }
+ if (e.isConsumed())
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public Dimension getPreferredScrollableViewportSize()
+ {
+ return getPreferredSize();
+ }
+
+ @Override
+ public int getScrollableBlockIncrement(Rectangle visibleRect,
+ int orientation, int direction)
+ {
+ return 30;
+ }
+
+ @Override
+ public boolean getScrollableTracksViewportHeight()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean getScrollableTracksViewportWidth()
+ {
+ return true;
+ }
+
+ @Override
+ public int getScrollableUnitIncrement(Rectangle visibleRect,
+ int orientation, int direction)
+ {
+ return 30;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * java.awt.event.AdjustmentListener#adjustmentValueChanged(java.awt.event
+ * .AdjustmentEvent)
*/
@Override
public void adjustmentValueChanged(AdjustmentEvent evt)
{
+ // update annotation label display
ap.alabels.setScrollOffset(-evt.getValue());
}
* Calculates the height of the annotation displayed in the annotation panel.
* Callers should normally call the ap.adjustAnnotationHeight method to ensure
* all annotation associated components are updated correctly.
- *
+ *
*/
public int adjustPanelHeight()
{
/**
* DOCUMENT ME!
- *
+ *
* @param evt
* DOCUMENT ME!
*/
else if (evt.getActionCommand().equals(LABEL))
{
String exMesg = collectAnnotVals(anot, av.getColumnSelection(), LABEL);
- String label = JOptionPane.showInputDialog(this, "Enter label",
+ String label = JOptionPane.showInputDialog(this, MessageManager.getString("label.enter_label"),
exMesg);
if (label == null)
}
String label = JOptionPane.showInputDialog(
- "Enter a label for the structure?", symbol);
+ MessageManager.getString("label.enter_label_for_the_structure"), symbol);
if (label == null)
{
if ((label.length() > 0) && !aa[activeRow].hasText)
{
aa[activeRow].hasText = true;
+ if (evt.getActionCommand().equals(STEM))
+ {
+ aa[activeRow].showAllColLabels=true;
+ }
}
-
for (int i = 0; i < av.getColumnSelection().size(); i++)
{
int index = av.getColumnSelection().columnAt(i);
anot[index].secondaryStructure = type;
anot[index].displayCharacter = label;
+
}
}
- aa[activeRow].validateRangeAndDisplay();
-
- adjustPanelHeight();
+ av.getAlignment().validateAnnotation(aa[activeRow]);
ap.alignmentChanged();
+
+ adjustPanelHeight();
repaint();
return;
{
String collatedInput = "";
String last = "";
- ColumnSelection viscols=av.getColumnSelection();
+ ColumnSelection viscols = av.getColumnSelection();
// TODO: refactor and save av.getColumnSelection for efficiency
for (int i = 0; i < columnSelection.size(); i++)
{
/**
* DOCUMENT ME!
- *
+ *
* @param evt
* DOCUMENT ME!
*/
return;
}
- JPopupMenu pop = new JPopupMenu("Structure type");
+ JPopupMenu pop = new JPopupMenu(MessageManager.getString("label.structure_type"));
JMenuItem item;
/*
* Just display the needed structure options
/**
* DOCUMENT ME!
- *
+ *
* @param evt
* DOCUMENT ME!
*/
/**
* DOCUMENT ME!
- *
+ *
* @param evt
* DOCUMENT ME!
*/
/**
* DOCUMENT ME!
- *
+ *
* @param evt
* DOCUMENT ME!
*/
/**
* DOCUMENT ME!
- *
+ *
* @param evt
* DOCUMENT ME!
*/
/**
* DOCUMENT ME!
- *
+ *
* @param evt
* DOCUMENT ME!
*/
&& aa[row].annotations[res].description != null
&& aa[row].annotations[res].description.length() > 0)
{
- this.setToolTipText(aa[row].annotations[res].description);
+ this.setToolTipText("<html>"+JvSwingUtils.wrapTooltip(aa[row].annotations[res].description)+"</html>");
}
else
{
/**
* DOCUMENT ME!
- *
+ *
* @param evt
* DOCUMENT ME!
*/
@Override
public void mouseClicked(MouseEvent evt)
{
- if (activeRow != -1)
- {
- AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
- AlignmentAnnotation anot = aa[activeRow];
-
- if (anot.description.equals("secondary structure"))
- {
- // System.out.println(anot.description+" "+anot.getRNAStruc());
- }
- }
+// if (activeRow != -1)
+// {
+// AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
+// AlignmentAnnotation anot = aa[activeRow];
+// }
}
// TODO mouseClicked-content and drawCursor are quite experimental!
}
}
- private volatile boolean imageFresh=false;
+
+ private volatile boolean imageFresh = false;
+
/**
* DOCUMENT ME!
- *
+ *
* @param g
* DOCUMENT ME!
*/
imgWidth = (av.endRes - av.startRes + 1) * av.charWidth;
if (imgWidth < 1)
return;
- if (image == null || imgWidth != image.getWidth()
+ if (image == null || imgWidth != image.getWidth(this)
|| image.getHeight(this) != getHeight())
{
- image = new BufferedImage(imgWidth, ap.annotationPanel.getHeight(),
- BufferedImage.TYPE_INT_RGB);
+ try
+ {
+ image = new BufferedImage(imgWidth, ap.annotationPanel.getHeight(),
+ BufferedImage.TYPE_INT_RGB);
+ } catch (OutOfMemoryError oom)
+ {
+ try
+ {
+ System.gc();
+ } catch (Exception x)
+ {
+ }
+ ;
+ new OOMWarning(
+ "Couldn't allocate memory to redraw screen. Please restart Jalview",
+ oom);
+ return;
+ }
gg = (Graphics2D) image.getGraphics();
if (av.antiAlias)
fm = gg.getFontMetrics();
gg.setColor(Color.white);
gg.fillRect(0, 0, imgWidth, image.getHeight());
- imageFresh=true;
+ imageFresh = true;
}
drawComponent(gg, av.startRes, av.endRes + 1);
- imageFresh=false;
+ imageFresh = false;
g.drawImage(image, 0, 0, this);
}
-
+ /**
+ * set true to enable redraw timing debug output on stderr
+ */
+ private final boolean debugRedraw = false;
/**
* non-Thread safe repaint
- *
+ *
* @param horizontal
* repaint with horizontal shift in alignment
*/
public void fastPaint(int horizontal)
{
-
if ((horizontal == 0) || gg == null
|| av.getAlignment().getAlignmentAnnotation() == null
|| av.getAlignment().getAlignmentAnnotation().length < 1
repaint();
return;
}
+ long stime=System.currentTimeMillis();
gg.copyArea(0, 0, imgWidth, getHeight(), -horizontal * av.charWidth, 0);
-
+ long mtime=System.currentTimeMillis();
int sr = av.startRes;
int er = av.endRes + 1;
int transX = 0;
drawComponent(gg, sr, er);
gg.translate(-transX, 0);
-
+ long dtime=System.currentTimeMillis();
fastPaint = true;
repaint();
+ long rtime=System.currentTimeMillis();
+ if (debugRedraw) {
+ System.err.println("Scroll:\t"+horizontal+"\tCopyArea:\t"+(mtime-stime)+"\tDraw component:\t"+(dtime-mtime)+"\tRepaint call:\t"+(rtime-dtime));
+ }
}
- private volatile boolean lastImageGood=false;
+
+ private volatile boolean lastImageGood = false;
+
/**
* DOCUMENT ME!
- *
+ *
* @param g
* DOCUMENT ME!
* @param startRes
*/
public void drawComponent(Graphics g, int startRes, int endRes)
{
- BufferedImage oldFaded=fadedImage;
+ BufferedImage oldFaded = fadedImage;
if (av.isCalcInProgress())
{
if (image == null)
{
- lastImageGood=false;
+ lastImageGood = false;
return;
}
// We'll keep a record of the old image,
// and draw a faded image until the calculation
// has completed
- if (lastImageGood && (fadedImage == null || fadedImage.getWidth() != imgWidth
- || fadedImage.getHeight() != image.getHeight()))
+ if (lastImageGood
+ && (fadedImage == null || fadedImage.getWidth() != imgWidth || fadedImage
+ .getHeight() != image.getHeight()))
{
-// System.err.println("redraw faded image ("+(fadedImage==null ? "null image" : "") + " lastGood="+lastImageGood+")");
+ // System.err.println("redraw faded image ("+(fadedImage==null ?
+ // "null image" : "") + " lastGood="+lastImageGood+")");
fadedImage = new BufferedImage(imgWidth, image.getHeight(),
BufferedImage.TYPE_INT_RGB);
fadedG.drawImage(image, 0, 0, this);
}
- // make sure we don't overwrite the last good faded image until all calculations have finished
- lastImageGood=false;
+ // make sure we don't overwrite the last good faded image until all
+ // calculations have finished
+ lastImageGood = false;
}
else
{
- if (fadedImage!=null)
+ if (fadedImage != null)
{
- oldFaded=fadedImage;
+ oldFaded = fadedImage;
}
fadedImage = null;
}
-
+
g.setColor(Color.white);
g.fillRect(0, 0, (endRes - startRes) * av.charWidth, getHeight());
g.setColor(Color.black);
if (av.validCharWidth)
{
- g.drawString("Alignment has no annotations", 20, 15);
+ g.drawString(MessageManager.getString("label.alignment_has_no_annotations"), 20, 15);
}
return;
}
- lastImageGood = renderer.drawComponent(this, av, g, activeRow, startRes, endRes);
- if (!lastImageGood && fadedImage==null)
+ lastImageGood = renderer.drawComponent(this, av, g, activeRow,
+ startRes, endRes);
+ if (!lastImageGood && fadedImage == null)
{
- fadedImage=oldFaded;
+ fadedImage = oldFaded;
}
}
{
return imgWidth;
}
+ private int[] bounds = new int[2];
+ @Override
+ public int[] getVisibleVRange()
+ {
+ if (ap!=null && ap.alabels!=null)
+ {
+ int sOffset=-ap.alabels.scrollOffset;
+ int visHeight = sOffset+ap.annotationSpaceFillerHolder.getHeight();
+ bounds[0] = sOffset; bounds[1]=visHeight;
+ return bounds;
+ } else return null;
+ }
}