2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.Annotation;
25 import jalview.datamodel.ColumnSelection;
26 import jalview.datamodel.HiddenColumns;
27 import jalview.datamodel.SequenceI;
28 import jalview.gui.JalviewColourChooser.ColourChooserListener;
29 import jalview.renderer.AnnotationRenderer;
30 import jalview.renderer.AwtRenderPanelI;
31 import jalview.schemes.ResidueProperties;
32 import jalview.util.Comparison;
33 import jalview.util.MessageManager;
34 import jalview.viewmodel.ViewportListenerI;
35 import jalview.viewmodel.ViewportRanges;
37 import java.awt.AlphaComposite;
38 import java.awt.Color;
39 import java.awt.Dimension;
40 import java.awt.FontMetrics;
41 import java.awt.Graphics;
42 import java.awt.Graphics2D;
43 import java.awt.Image;
44 import java.awt.Rectangle;
45 import java.awt.RenderingHints;
46 import java.awt.event.ActionEvent;
47 import java.awt.event.ActionListener;
48 import java.awt.event.AdjustmentEvent;
49 import java.awt.event.AdjustmentListener;
50 import java.awt.event.MouseEvent;
51 import java.awt.event.MouseListener;
52 import java.awt.event.MouseMotionListener;
53 import java.awt.event.MouseWheelEvent;
54 import java.awt.event.MouseWheelListener;
55 import java.awt.image.BufferedImage;
56 import java.beans.PropertyChangeEvent;
57 import java.util.ArrayList;
58 import java.util.Collections;
59 import java.util.List;
61 import javax.swing.JMenuItem;
62 import javax.swing.JPanel;
63 import javax.swing.JPopupMenu;
64 import javax.swing.Scrollable;
65 import javax.swing.ToolTipManager;
68 * AnnotationPanel displays visible portion of annotation rows below unwrapped
74 public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
75 MouseListener, MouseWheelListener, MouseMotionListener,
76 ActionListener, AdjustmentListener, Scrollable, ViewportListenerI
80 Select, Resize, Undefined
83 String HELIX = MessageManager.getString("label.helix");
85 String SHEET = MessageManager.getString("label.sheet");
88 * For RNA secondary structure "stems" aka helices
90 String STEM = MessageManager.getString("label.rna_helix");
92 String LABEL = MessageManager.getString("label.label");
94 String REMOVE = MessageManager.getString("label.remove_annotation");
96 String COLOUR = MessageManager.getString("action.colour");
98 public final Color HELIX_COLOUR = Color.red.darker();
100 public final Color SHEET_COLOUR = Color.green.darker().darker();
102 public final Color STEM_COLOUR = Color.blue.darker();
105 public AlignViewport av;
109 public int activeRow = -1;
111 public BufferedImage image;
113 public volatile BufferedImage fadedImage;
117 public FontMetrics fm;
119 public int imgWidth = 0;
121 boolean fastPaint = false;
123 // Used For mouse Dragging and resizing graphs
124 int graphStretch = -1;
126 int mouseDragLastX = -1;
128 int mouseDragLastY = -1;
130 DragMode dragMode = DragMode.Undefined;
132 boolean mouseDragging = false;
134 // for editing cursor
139 public final AnnotationRenderer renderer;
141 private MouseWheelListener[] _mwl;
144 * Creates a new AnnotationPanel object.
149 public AnnotationPanel(AlignmentPanel ap)
151 ToolTipManager.sharedInstance().registerComponent(this);
152 ToolTipManager.sharedInstance().setInitialDelay(0);
153 ToolTipManager.sharedInstance().setDismissDelay(10000);
156 this.setLayout(null);
157 addMouseListener(this);
158 addMouseMotionListener(this);
159 ap.annotationScroller.getVerticalScrollBar()
160 .addAdjustmentListener(this);
161 // save any wheel listeners on the scroller, so we can propagate scroll
163 _mwl = ap.annotationScroller.getMouseWheelListeners();
164 // and then set our own listener to consume all mousewheel events
165 ap.annotationScroller.addMouseWheelListener(this);
166 renderer = new AnnotationRenderer();
168 av.getRanges().addPropertyChangeListener(this);
171 public AnnotationPanel(AlignViewport av)
174 renderer = new AnnotationRenderer();
178 public void mouseWheelMoved(MouseWheelEvent e)
183 double wheelRotation = e.getPreciseWheelRotation();
184 if (wheelRotation > 0)
186 av.getRanges().scrollRight(true);
188 else if (wheelRotation < 0)
190 av.getRanges().scrollRight(false);
195 // TODO: find the correct way to let the event bubble up to
196 // ap.annotationScroller
197 for (MouseWheelListener mwl : _mwl)
201 mwl.mouseWheelMoved(e);
212 public Dimension getPreferredScrollableViewportSize()
214 return getPreferredSize();
218 public int getScrollableBlockIncrement(Rectangle visibleRect,
219 int orientation, int direction)
225 public boolean getScrollableTracksViewportHeight()
231 public boolean getScrollableTracksViewportWidth()
237 public int getScrollableUnitIncrement(Rectangle visibleRect,
238 int orientation, int direction)
247 * java.awt.event.AdjustmentListener#adjustmentValueChanged(java.awt.event
251 public void adjustmentValueChanged(AdjustmentEvent evt)
253 // update annotation label display
254 ap.getAlabels().setScrollOffset(-evt.getValue());
258 * Calculates the height of the annotation displayed in the annotation panel.
259 * Callers should normally call the ap.adjustAnnotationHeight method to ensure
260 * all annotation associated components are updated correctly.
263 public int adjustPanelHeight()
265 int height = av.calcPanelHeight();
266 this.setPreferredSize(new Dimension(1, height));
269 // revalidate only when the alignment panel is fully constructed
283 public void actionPerformed(ActionEvent evt)
285 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
290 Annotation[] anot = aa[activeRow].annotations;
292 if (anot.length < av.getColumnSelection().getMax())
294 Annotation[] temp = new Annotation[av.getColumnSelection().getMax()
296 System.arraycopy(anot, 0, temp, 0, anot.length);
298 aa[activeRow].annotations = anot;
301 String action = evt.getActionCommand();
302 if (action.equals(REMOVE))
304 for (int index : av.getColumnSelection().getSelected())
306 if (av.getAlignment().getHiddenColumns().isVisible(index))
312 else if (action.equals(LABEL))
314 String exMesg = collectAnnotVals(anot, LABEL);
315 String label = JvOptionPane.showInputDialog(this,
316 MessageManager.getString("label.enter_label"), exMesg);
323 if ((label.length() > 0) && !aa[activeRow].hasText)
325 aa[activeRow].hasText = true;
328 for (int index : av.getColumnSelection().getSelected())
330 if (!av.getAlignment().getHiddenColumns().isVisible(index))
335 if (anot[index] == null)
337 anot[index] = new Annotation(label, "", ' ', 0);
341 anot[index].displayCharacter = label;
345 else if (action.equals(COLOUR))
347 final Annotation[] fAnot = anot;
348 String title = MessageManager
349 .getString("label.select_foreground_colour");
350 ColourChooserListener listener = new ColourChooserListener()
353 public void colourSelected(Color c)
355 HiddenColumns hiddenColumns = av.getAlignment().getHiddenColumns();
356 for (int index : av.getColumnSelection().getSelected())
358 if (hiddenColumns.isVisible(index))
360 if (fAnot[index] == null)
362 fAnot[index] = new Annotation("", "", ' ', 0);
364 fAnot[index].colour = c;
368 JalviewColourChooser.showColourChooser(this,
369 title, Color.black, listener);
372 // HELIX, SHEET or STEM
375 String symbol = "\u03B1"; // alpha
377 if (action.equals(HELIX))
381 else if (action.equals(SHEET))
384 symbol = "\u03B2"; // beta
387 // Added by LML to color stems
388 else if (action.equals(STEM))
391 int column = av.getColumnSelection().getSelectedRanges().get(0)[0];
392 symbol = aa[activeRow].getDefaultRnaHelixSymbol(column);
395 if (!aa[activeRow].hasIcons)
397 aa[activeRow].hasIcons = true;
400 String label = JvOptionPane.showInputDialog(MessageManager
401 .getString("label.enter_label_for_the_structure"), symbol);
408 if ((label.length() > 0) && !aa[activeRow].hasText)
410 aa[activeRow].hasText = true;
411 if (action.equals(STEM))
413 aa[activeRow].showAllColLabels = true;
416 for (int index : av.getColumnSelection().getSelected())
418 if (!av.getAlignment().getHiddenColumns().isVisible(index))
423 if (anot[index] == null)
425 anot[index] = new Annotation(label, "", type, 0);
428 anot[index].secondaryStructure = type != 'S' ? type
429 : label.length() == 0 ? ' ' : label.charAt(0);
430 anot[index].displayCharacter = label;
435 av.getAlignment().validateAnnotation(aa[activeRow]);
436 ap.alignmentChanged();
437 ap.alignFrame.setMenusForViewport();
445 * Returns any existing annotation concatenated as a string. For each
446 * annotation, takes the description, if any, else the secondary structure
447 * character (if type is HELIX, SHEET or STEM), else the display character (if
454 private String collectAnnotVals(Annotation[] anots, String type)
456 // TODO is this method wanted? why? 'last' is not used
458 StringBuilder collatedInput = new StringBuilder(64);
460 ColumnSelection viscols = av.getColumnSelection();
461 HiddenColumns hidden = av.getAlignment().getHiddenColumns();
464 * the selection list (read-only view) is in selection order, not
465 * column order; make a copy so we can sort it
467 List<Integer> selected = new ArrayList<>(viscols.getSelected());
468 Collections.sort(selected);
469 for (int index : selected)
471 // always check for current display state - just in case
472 if (!hidden.isVisible(index))
476 String tlabel = null;
477 if (anots[index] != null)
478 { // LML added stem code
479 if (type.equals(HELIX) || type.equals(SHEET) || type.equals(STEM)
480 || type.equals(LABEL))
482 tlabel = anots[index].description;
483 if (tlabel == null || tlabel.length() < 1)
485 if (type.equals(HELIX) || type.equals(SHEET)
486 || type.equals(STEM))
488 tlabel = "" + anots[index].secondaryStructure;
492 tlabel = "" + anots[index].displayCharacter;
496 if (tlabel != null && !tlabel.equals(last))
498 if (last.length() > 0)
500 collatedInput.append(" ");
502 collatedInput.append(tlabel);
506 return collatedInput.toString();
510 * Action on right mouse pressed on Mac is to show a pop-up menu for the
511 * annotation. Action on left mouse pressed is to find which annotation is
512 * pressed and mark the start of a column selection or graph resize operation.
517 public void mousePressed(MouseEvent evt)
520 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
525 mouseDragLastX = evt.getX();
526 mouseDragLastY = evt.getY();
529 * add visible annotation heights until we reach the y
530 * position, to find which annotation it is in
535 final int y = evt.getY();
536 for (int i = 0; i < aa.length; i++)
540 height += aa[i].height;
549 else if (aa[i].graph > 0)
552 * we have clicked on a resizable graph annotation
561 * isPopupTrigger fires in mousePressed on Mac,
562 * not until mouseRelease on Windows
564 if (evt.isPopupTrigger() && activeRow != -1)
566 showPopupMenu(y, evt.getX());
570 ap.getScalePanel().mousePressed(evt);
574 * Construct and display a context menu at the right-click position
579 void showPopupMenu(final int y, int x)
581 if (av.getColumnSelection() == null
582 || av.getColumnSelection().isEmpty())
587 JPopupMenu pop = new JPopupMenu(
588 MessageManager.getString("label.structure_type"));
591 * Just display the needed structure options
593 if (av.getAlignment().isNucleotide())
595 item = new JMenuItem(STEM);
596 item.addActionListener(this);
601 item = new JMenuItem(HELIX);
602 item.addActionListener(this);
604 item = new JMenuItem(SHEET);
605 item.addActionListener(this);
608 item = new JMenuItem(LABEL);
609 item.addActionListener(this);
611 item = new JMenuItem(COLOUR);
612 item.addActionListener(this);
614 item = new JMenuItem(REMOVE);
615 item.addActionListener(this);
617 pop.show(this, x, y);
621 * Action on mouse up is to clear mouse drag data and call mouseReleased on
622 * ScalePanel, to deal with defining the selection group (if any) defined by
628 public void mouseReleased(MouseEvent evt)
633 mouseDragging = false;
634 dragMode = DragMode.Undefined;
635 ap.getScalePanel().mouseReleased(evt);
638 * isPopupTrigger is set in mouseReleased on Windows
639 * (in mousePressed on Mac)
641 if (evt.isPopupTrigger() && activeRow != -1)
643 showPopupMenu(evt.getY(), evt.getX());
655 public void mouseEntered(MouseEvent evt)
657 this.mouseDragging = false;
658 ap.getScalePanel().mouseEntered(evt);
662 * On leaving the panel, calls ScalePanel.mouseExited to deal with scrolling
663 * with column selection on a mouse drag
668 public void mouseExited(MouseEvent evt)
670 ap.getScalePanel().mouseExited(evt);
680 public void mouseDragged(MouseEvent evt)
683 * todo: if dragMode is Undefined:
684 * - set to Select if dx > dy
685 * - set to Resize if dy > dx
686 * - do nothing if dx == dy
688 final int x = evt.getX();
689 final int y = evt.getY();
690 if (dragMode == DragMode.Undefined)
692 int dx = Math.abs(x - mouseDragLastX);
693 int dy = Math.abs(y - mouseDragLastY);
694 if (graphStretch == -1 || dx > dy)
697 * mostly horizontal drag, or not a graph annotation
699 dragMode = DragMode.Select;
704 * mostly vertical drag
706 dragMode = DragMode.Resize;
710 if (dragMode == DragMode.Undefined)
713 * drag is diagonal - defer deciding whether to
714 * treat as up/down or left/right
721 if (dragMode == DragMode.Resize)
724 * resize graph annotation if mouse was dragged up or down
726 int deltaY = mouseDragLastY - evt.getY();
729 AlignmentAnnotation graphAnnotation = av.getAlignment()
730 .getAlignmentAnnotation()[graphStretch];
731 int newHeight = Math.max(0, graphAnnotation.graphHeight + deltaY);
732 graphAnnotation.graphHeight = newHeight;
734 ap.paintAlignment(false, false);
740 * for mouse drag left or right, delegate to
741 * ScalePanel to adjust the column selection
743 ap.getScalePanel().mouseDragged(evt);
753 * Constructs the tooltip, and constructs and displays a status message, for
754 * the current mouse position
759 public void mouseMoved(MouseEvent evt)
761 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
765 this.setToolTipText(null);
772 for (int i = 0; i < aa.length; i++)
776 height += aa[i].height;
779 if (evt.getY() < height)
788 this.setToolTipText(null);
792 int column = (evt.getX() / av.getCharWidth())
793 + av.getRanges().getStartRes();
795 if (av.hasHiddenColumns())
797 column = av.getAlignment().getHiddenColumns()
798 .visibleToAbsoluteColumn(column);
801 AlignmentAnnotation ann = aa[row];
802 if (row > -1 && ann.annotations != null
803 && column < ann.annotations.length)
805 buildToolTip(ann, column, aa);
806 setStatusMessage(column, ann);
810 this.setToolTipText(null);
811 ap.alignFrame.statusBar.setText(" ");
816 * Builds a tooltip for the annotation at the current mouse position.
822 void buildToolTip(AlignmentAnnotation ann, int column,
823 AlignmentAnnotation[] anns)
825 if (ann.graphGroup > -1)
827 StringBuilder tip = new StringBuilder(32);
828 tip.append("<html>");
829 for (int i = 0; i < anns.length; i++)
831 if (anns[i].graphGroup == ann.graphGroup
832 && anns[i].annotations[column] != null)
834 tip.append(anns[i].label);
835 String description = anns[i].annotations[column].description;
836 if (description != null && description.length() > 0)
838 tip.append(" ").append(description);
843 if (tip.length() != 6)
845 tip.setLength(tip.length() - 4);
846 this.setToolTipText(tip.toString() + "</html>");
849 else if (ann.annotations[column] != null)
851 String description = ann.annotations[column].description;
852 if (description != null && description.length() > 0)
854 this.setToolTipText(JvSwingUtils.wrapTooltip(true, description));
858 this.setToolTipText(null); // no tooltip if null or empty description
863 // clear the tooltip.
864 this.setToolTipText(null);
869 * Constructs and displays the status bar message
874 void setStatusMessage(int column, AlignmentAnnotation ann)
877 * show alignment column and annotation description if any
879 StringBuilder text = new StringBuilder(32);
880 text.append(MessageManager.getString("label.column")).append(" ")
883 if (ann.annotations[column] != null)
885 String description = ann.annotations[column].description;
886 if (description != null && description.trim().length() > 0)
888 text.append(" ").append(description);
893 * if the annotation is sequence-specific, show the sequence number
894 * in the alignment, and (if not a gap) the residue and position
896 SequenceI seqref = ann.sequenceRef;
899 int seqIndex = av.getAlignment().findIndex(seqref);
902 text.append(", ").append(MessageManager.getString("label.sequence"))
903 .append(" ").append(seqIndex + 1);
904 char residue = seqref.getCharAt(column);
905 if (!Comparison.isGap(residue))
909 if (av.getAlignment().isNucleotide())
911 name = ResidueProperties.nucleotideName
912 .get(String.valueOf(residue));
913 text.append(" Nucleotide: ")
914 .append(name != null ? name : residue);
918 name = 'X' == residue ? "X"
919 : ('*' == residue ? "STOP"
920 : ResidueProperties.aa2Triplet
921 .get(String.valueOf(residue)));
922 text.append(" Residue: ").append(name != null ? name : residue);
924 int residuePos = seqref.findPosition(column);
925 text.append(" (").append(residuePos).append(")");
930 ap.alignFrame.statusBar.setText(text.toString());
940 public void mouseClicked(MouseEvent evt)
942 // if (activeRow != -1)
944 // AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
945 // AlignmentAnnotation anot = aa[activeRow];
949 // TODO mouseClicked-content and drawCursor are quite experimental!
950 public void drawCursor(Graphics graphics, SequenceI seq, int res, int x1,
953 int pady = av.getCharHeight() / 5;
955 graphics.setColor(Color.black);
956 graphics.fillRect(x1, y1, av.getCharWidth(), av.getCharHeight());
958 if (av.validCharWidth)
960 graphics.setColor(Color.white);
962 char s = seq.getCharAt(res);
964 charOffset = (av.getCharWidth() - fm.charWidth(s)) / 2;
965 graphics.drawString(String.valueOf(s), charOffset + x1,
966 (y1 + av.getCharHeight()) - pady);
971 private volatile boolean imageFresh = false;
980 public void paintComponent(Graphics g)
982 super.paintComponent(g);
984 g.setColor(Color.white);
985 g.fillRect(0, 0, getWidth(), getHeight());
989 if (fastPaint || (getVisibleRect().width != g.getClipBounds().width)
990 || (getVisibleRect().height != g.getClipBounds().height))
992 g.drawImage(image, 0, 0, this);
997 imgWidth = (av.getRanges().getEndRes() - av.getRanges().getStartRes()
998 + 1) * av.getCharWidth();
1003 if (image == null || imgWidth != image.getWidth(this)
1004 || image.getHeight(this) != getHeight())
1008 image = new BufferedImage(imgWidth,
1009 ap.getAnnotationPanel().getHeight(),
1010 BufferedImage.TYPE_INT_RGB);
1011 } catch (OutOfMemoryError oom)
1016 } catch (Exception x)
1021 "Couldn't allocate memory to redraw screen. Please restart Jalview",
1025 gg = (Graphics2D) image.getGraphics();
1029 gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1030 RenderingHints.VALUE_ANTIALIAS_ON);
1033 gg.setFont(av.getFont());
1034 fm = gg.getFontMetrics();
1035 gg.setColor(Color.white);
1036 gg.fillRect(0, 0, imgWidth, image.getHeight());
1040 drawComponent(gg, av.getRanges().getStartRes(),
1041 av.getRanges().getEndRes() + 1);
1043 g.drawImage(image, 0, 0, this);
1047 * set true to enable redraw timing debug output on stderr
1049 private final boolean debugRedraw = false;
1052 * non-Thread safe repaint
1055 * repaint with horizontal shift in alignment
1057 public void fastPaint(int horizontal)
1059 if ((horizontal == 0) || gg == null
1060 || av.getAlignment().getAlignmentAnnotation() == null
1061 || av.getAlignment().getAlignmentAnnotation().length < 1
1062 || av.isCalcInProgress())
1068 int sr = av.getRanges().getStartRes();
1069 int er = av.getRanges().getEndRes() + 1;
1072 gg.copyArea(0, 0, imgWidth, getHeight(),
1073 -horizontal * av.getCharWidth(), 0);
1075 if (horizontal > 0) // scrollbar pulled right, image to the left
1077 transX = (er - sr - horizontal) * av.getCharWidth();
1078 sr = er - horizontal;
1080 else if (horizontal < 0)
1082 er = sr - horizontal;
1085 gg.translate(transX, 0);
1087 drawComponent(gg, sr, er);
1089 gg.translate(-transX, 0);
1093 // Call repaint on alignment panel so that repaints from other alignment
1094 // panel components can be aggregated. Otherwise performance of the overview
1095 // window and others may be adversely affected.
1096 av.getAlignPanel().repaint();
1099 private volatile boolean lastImageGood = false;
1111 public void drawComponent(Graphics g, int startRes, int endRes)
1113 BufferedImage oldFaded = fadedImage;
1114 if (av.isCalcInProgress())
1118 lastImageGood = false;
1121 // We'll keep a record of the old image,
1122 // and draw a faded image until the calculation
1125 && (fadedImage == null || fadedImage.getWidth() != imgWidth
1126 || fadedImage.getHeight() != image.getHeight()))
1128 // System.err.println("redraw faded image ("+(fadedImage==null ?
1129 // "null image" : "") + " lastGood="+lastImageGood+")");
1130 fadedImage = new BufferedImage(imgWidth, image.getHeight(),
1131 BufferedImage.TYPE_INT_RGB);
1133 Graphics2D fadedG = (Graphics2D) fadedImage.getGraphics();
1135 fadedG.setColor(Color.white);
1136 fadedG.fillRect(0, 0, imgWidth, image.getHeight());
1138 fadedG.setComposite(
1139 AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .3f));
1140 fadedG.drawImage(image, 0, 0, this);
1143 // make sure we don't overwrite the last good faded image until all
1144 // calculations have finished
1145 lastImageGood = false;
1150 if (fadedImage != null)
1152 oldFaded = fadedImage;
1157 g.setColor(Color.white);
1158 g.fillRect(0, 0, (endRes - startRes) * av.getCharWidth(), getHeight());
1160 g.setFont(av.getFont());
1163 fm = g.getFontMetrics();
1166 if ((av.getAlignment().getAlignmentAnnotation() == null)
1167 || (av.getAlignment().getAlignmentAnnotation().length < 1))
1169 g.setColor(Color.white);
1170 g.fillRect(0, 0, getWidth(), getHeight());
1171 g.setColor(Color.black);
1172 if (av.validCharWidth)
1174 g.drawString(MessageManager
1175 .getString("label.alignment_has_no_annotations"), 20, 15);
1180 lastImageGood = renderer.drawComponent(this, av, g, activeRow, startRes,
1182 if (!lastImageGood && fadedImage == null)
1184 fadedImage = oldFaded;
1189 public FontMetrics getFontMetrics()
1195 public Image getFadedImage()
1201 public int getFadedImageWidth()
1206 private int[] bounds = new int[2];
1209 public int[] getVisibleVRange()
1211 if (ap != null && ap.getAlabels() != null)
1213 int sOffset = -ap.getAlabels().getScrollOffset();
1214 int visHeight = sOffset + ap.annotationSpaceFillerHolder.getHeight();
1215 bounds[0] = sOffset;
1216 bounds[1] = visHeight;
1226 * Try to ensure any references held are nulled
1228 public void dispose()
1238 * I created the renderer so I will dispose of it
1240 if (renderer != null)
1247 public void propertyChange(PropertyChangeEvent evt)
1249 // Respond to viewport range changes (e.g. alignment panel was scrolled)
1250 // Both scrolling and resizing change viewport ranges: scrolling changes
1251 // both start and end points, but resize only changes end values.
1252 // Here we only want to fastpaint on a scroll, with resize using a normal
1253 // paint, so scroll events are identified as changes to the horizontal or
1254 // vertical start value.
1255 if (evt.getPropertyName().equals(ViewportRanges.STARTRES))
1257 fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
1259 else if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
1261 fastPaint(((int[]) evt.getNewValue())[0]
1262 - ((int[]) evt.getOldValue())[0]);
1264 else if (evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))