X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FAnnotationPanel.java;h=92cd407c90a9977b4c936ce1c4af56bb0f499d1e;hb=4cea7a0328724b90a6a7c16ae8c926e0cc12cedd;hp=03670d2e98c9245f8eabf95970c682b9d182b695;hpb=e8ede151da126e8fe205392c64f1604d80adda6d;p=jalview.git diff --git a/src/jalview/gui/AnnotationPanel.java b/src/jalview/gui/AnnotationPanel.java index 03670d2..92cd407 100755 --- a/src/jalview/gui/AnnotationPanel.java +++ b/src/jalview/gui/AnnotationPanel.java @@ -1,18 +1,18 @@ /* - * 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) + * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle + * * 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 . */ package jalview.gui; @@ -20,21 +20,24 @@ 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; /** - * DOCUMENT ME! - * + * 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"; @@ -96,9 +99,11 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, public final AnnotationRenderer renderer; + private MouseWheelListener[] _mwl; + /** * Creates a new AnnotationPanel object. - * + * * @param ap * DOCUMENT ME! */ @@ -117,6 +122,11 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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(); } @@ -126,15 +136,82 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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()); } @@ -142,7 +219,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, * 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() { @@ -159,7 +236,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, /** * DOCUMENT ME! - * + * * @param evt * DOCUMENT ME! */ @@ -191,7 +268,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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) @@ -273,7 +350,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, } String label = JOptionPane.showInputDialog( - "Enter a label for the structure?", symbol); + MessageManager.getString("label.enter_label_for_the_structure"), symbol); if (label == null) { @@ -301,10 +378,10 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, anot[index].displayCharacter = label; } } - aa[activeRow].validateRangeAndDisplay(); - - adjustPanelHeight(); + av.getAlignment().validateAnnotation(aa[activeRow]); ap.alignmentChanged(); + + adjustPanelHeight(); repaint(); return; @@ -315,7 +392,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, { 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++) { @@ -358,7 +435,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, /** * DOCUMENT ME! - * + * * @param evt * DOCUMENT ME! */ @@ -406,7 +483,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, return; } - JPopupMenu pop = new JPopupMenu("Structure type"); + JPopupMenu pop = new JPopupMenu(MessageManager.getString("label.structure_type")); JMenuItem item; /* * Just display the needed structure options @@ -451,7 +528,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, /** * DOCUMENT ME! - * + * * @param evt * DOCUMENT ME! */ @@ -466,7 +543,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, /** * DOCUMENT ME! - * + * * @param evt * DOCUMENT ME! */ @@ -478,7 +555,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, /** * DOCUMENT ME! - * + * * @param evt * DOCUMENT ME! */ @@ -490,7 +567,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, /** * DOCUMENT ME! - * + * * @param evt * DOCUMENT ME! */ @@ -517,7 +594,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, /** * DOCUMENT ME! - * + * * @param evt * DOCUMENT ME! */ @@ -588,7 +665,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, && aa[row].annotations[res].description != null && aa[row].annotations[res].description.length() > 0) { - this.setToolTipText(aa[row].annotations[res].description); + this.setToolTipText(""+JvSwingUtils.wrapTooltip(aa[row].annotations[res].description)+""); } else { @@ -617,23 +694,18 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, /** * 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! @@ -657,10 +729,12 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, } } - private volatile boolean imageFresh=false; + + private volatile boolean imageFresh = false; + /** * DOCUMENT ME! - * + * * @param g * DOCUMENT ME! */ @@ -683,11 +757,27 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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) @@ -700,23 +790,25 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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 @@ -725,8 +817,9 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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; @@ -746,15 +839,21 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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 @@ -764,21 +863,23 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, */ 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); @@ -792,19 +893,20 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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()); @@ -822,15 +924,16 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, 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; } } @@ -851,4 +954,16 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI, { 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; + } }