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.
21 package jalview.appletgui;
23 import jalview.datamodel.SequenceI;
24 import jalview.renderer.seqfeatures.FeatureColourFinder;
25 import jalview.viewmodel.OverviewDimensions;
26 import jalview.viewmodel.ViewportListenerI;
28 import java.awt.Color;
29 import java.awt.Dimension;
30 import java.awt.Frame;
31 import java.awt.Graphics;
32 import java.awt.Image;
33 import java.awt.Panel;
34 import java.awt.event.ComponentAdapter;
35 import java.awt.event.ComponentEvent;
36 import java.awt.event.MouseEvent;
37 import java.awt.event.MouseListener;
38 import java.awt.event.MouseMotionListener;
39 import java.beans.PropertyChangeEvent;
41 public class OverviewPanel extends Panel implements Runnable,
42 MouseMotionListener, MouseListener, ViewportListenerI
44 private OverviewDimensions od;
48 private Image offscreen;
50 private AlignViewport av;
52 private AlignmentPanel ap;
54 private boolean resizing = false;
56 // This is set true if the user resizes whilst
57 // the overview is being calculated
58 private boolean resizeAgain = false;
60 // Can set different properties in this seqCanvas than
61 // main visible SeqCanvas
62 private SequenceRenderer sr;
64 private FeatureRenderer fr;
66 private Frame nullFrame;
68 public OverviewPanel(AlignmentPanel alPanel)
73 nullFrame = new Frame();
74 nullFrame.addNotify();
76 sr = new SequenceRenderer(av);
77 sr.graphics = nullFrame.getGraphics();
78 sr.renderGaps = false;
79 sr.forOverview = true;
80 fr = new FeatureRenderer(av);
82 od = new OverviewDimensions(av.getRanges(),
83 (av.isShowAnnotation() && av.getSequenceConsensusHash() != null));
85 setSize(new Dimension(od.getWidth(), od.getHeight()));
87 av.getRanges().addPropertyChangeListener(this);
89 addComponentListener(new ComponentAdapter()
93 public void componentResized(ComponentEvent evt)
95 if ((getWidth() != od.getWidth())
96 || (getHeight() != (od.getHeight())))
98 updateOverviewImage();
103 addMouseMotionListener(this);
105 addMouseListener(this);
107 updateOverviewImage();
112 public void mouseEntered(MouseEvent evt)
117 public void mouseExited(MouseEvent evt)
122 public void mouseClicked(MouseEvent evt)
127 public void mouseMoved(MouseEvent evt)
132 public void mousePressed(MouseEvent evt)
138 public void mouseReleased(MouseEvent evt)
144 public void mouseDragged(MouseEvent evt)
149 private void mouseAction(MouseEvent evt)
151 od.updateViewportFromMouse(evt.getX(), evt.getY(), av.getAlignment()
152 .getHiddenSequences(), av.getColumnSelection(), av
154 // ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
155 ap.paintAlignment(false);
159 * Updates the overview image when the related alignment panel is updated
161 public void updateOverviewImage()
169 if (av.isShowSequenceFeatures())
171 fr.transferSettings(ap.seqPanel.seqCanvas.fr);
176 if ((getSize().width > 0) && (getSize().height > 0))
178 od.setWidth(getSize().width);
179 od.setHeight(getSize().height);
181 setSize(new Dimension(od.getWidth(), od.getHeight()));
183 Thread thread = new Thread(this);
193 if (av.isShowSequenceFeatures())
195 fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer());
198 if (getSize().width > 0 && getSize().height > 0)
200 od.setWidth(getSize().width);
201 od.setHeight(getSize().height);
204 setSize(new Dimension(od.getWidth(), od.getHeight()));
206 miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
207 offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
209 Graphics mg = miniMe.getGraphics();
211 int alwidth = av.getAlignment().getWidth();
212 int alheight = av.getAlignment().getAbsoluteHeight();
213 float sampleCol = alwidth / (float) od.getWidth();
214 float sampleRow = alheight / (float) od.getSequencesHeight();
216 buildImage(sampleRow, sampleCol, mg);
218 // check for conservation annotation to make sure overview works for DNA too
219 if (av.isShowAnnotation()
220 && (av.getAlignmentConservationAnnotation() != null))
222 for (int col = 0; col < od.getWidth() && !resizeAgain; col++)
224 mg.translate(col, od.getSequencesHeight());
225 ap.annotationPanel.renderer.drawGraph(mg,
226 av.getAlignmentConservationAnnotation(),
227 av.getAlignmentConservationAnnotation().annotations,
228 (int) (sampleCol) + 1, od.getGraphHeight(),
229 (int) (col * sampleCol), (int) (col * sampleCol) + 1);
230 mg.translate(-col, -od.getSequencesHeight());
242 updateOverviewImage();
247 * Build the overview panel image
249 private void buildImage(float sampleRow, float sampleCol, Graphics mg)
255 Color color = Color.yellow;
259 SequenceI seq = null;
260 FeatureColourFinder finder = new FeatureColourFinder(fr);
262 final boolean hasHiddenCols = av.hasHiddenColumns();
263 boolean hiddenRow = false;
265 for (int row = 0; row <= od.getSequencesHeight() && !resizeAgain; row++)
267 if ((int) (row * sampleRow) == lastrow)
273 // get the sequence which would be at alignment index 'lastrow' if no
274 // columns were hidden, and determine whether it is hidden or not
275 hiddenRow = av.getAlignment().isHidden(lastrow);
276 seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
278 for (int col = 0; col < od.getWidth(); col++)
280 if ((int) (col * sampleCol) == lastcol
281 && (int) (row * sampleRow) == lastrow)
287 lastcol = (int) (col * sampleCol);
289 color = getColumnColourFromSequence(seq, hiddenRow,
290 hasHiddenCols, lastcol, finder);
293 if (sameCol == 1 && sameRow == 1)
295 mg.drawLine(xstart, ystart, xstart, ystart);
299 mg.fillRect(xstart, ystart, sameCol, sameRow);
306 lastrow = (int) (row * sampleRow);
314 * Find the colour of a sequence at a specified column position
316 private Color getColumnColourFromSequence(
317 jalview.datamodel.SequenceI seq, boolean hiddenRow,
318 boolean hasHiddenCols, int lastcol, FeatureColourFinder finder)
320 Color color = Color.white;
321 if (seq.getLength() > lastcol)
323 color = sr.getResidueColour(seq, lastcol, finder);
327 || (hasHiddenCols && !av.getColumnSelection()
328 .isVisible(lastcol)))
330 color = color.darker().darker();
336 * Update the overview panel box when the associated alignment panel is
340 private void setBoxPosition()
342 od.setBoxPosition(av.getAlignment()
343 .getHiddenSequences(), av.getColumnSelection(), av.getRanges());
348 public void update(Graphics g)
354 public void paint(Graphics g)
356 Graphics og = offscreen.getGraphics();
359 og.drawImage(miniMe, 0, 0, this);
360 og.setColor(Color.red);
362 g.drawImage(offscreen, 0, 0, this);
367 public void propertyChange(PropertyChangeEvent evt)