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.paintAlignment(false);
158 * Updates the overview image when the related alignment panel is updated
160 public void updateOverviewImage()
168 if (av.isShowSequenceFeatures())
170 fr.transferSettings(ap.seqPanel.seqCanvas.fr);
175 if ((getSize().width > 0) && (getSize().height > 0))
177 od.setWidth(getSize().width);
178 od.setHeight(getSize().height);
180 setSize(new Dimension(od.getWidth(), od.getHeight()));
182 Thread thread = new Thread(this);
192 if (av.isShowSequenceFeatures())
194 fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer());
197 if (getSize().width > 0 && getSize().height > 0)
199 od.setWidth(getSize().width);
200 od.setHeight(getSize().height);
203 setSize(new Dimension(od.getWidth(), od.getHeight()));
205 miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
206 offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
208 Graphics mg = miniMe.getGraphics();
210 int alwidth = av.getAlignment().getWidth();
211 int alheight = av.getAlignment().getAbsoluteHeight();
212 float sampleCol = alwidth / (float) od.getWidth();
213 float sampleRow = alheight / (float) od.getSequencesHeight();
215 buildImage(sampleRow, sampleCol, mg);
217 // check for conservation annotation to make sure overview works for DNA too
218 if (av.isShowAnnotation()
219 && (av.getAlignmentConservationAnnotation() != null))
221 for (int col = 0; col < od.getWidth() && !resizeAgain; col++)
223 mg.translate(col, od.getSequencesHeight());
224 ap.annotationPanel.renderer.drawGraph(mg,
225 av.getAlignmentConservationAnnotation(),
226 av.getAlignmentConservationAnnotation().annotations,
227 (int) (sampleCol) + 1, od.getGraphHeight(),
228 (int) (col * sampleCol), (int) (col * sampleCol) + 1);
229 mg.translate(-col, -od.getSequencesHeight());
241 updateOverviewImage();
246 * Build the overview panel image
248 private void buildImage(float sampleRow, float sampleCol, Graphics mg)
254 Color color = Color.yellow;
258 SequenceI seq = null;
259 FeatureColourFinder finder = new FeatureColourFinder(fr);
261 final boolean hasHiddenCols = av.hasHiddenColumns();
262 boolean hiddenRow = false;
264 for (int row = 0; row <= od.getSequencesHeight() && !resizeAgain; row++)
266 if ((int) (row * sampleRow) == lastrow)
272 // get the sequence which would be at alignment index 'lastrow' if no
273 // columns were hidden, and determine whether it is hidden or not
274 hiddenRow = av.getAlignment().isHidden(lastrow);
275 seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
277 for (int col = 0; col < od.getWidth(); col++)
279 if ((int) (col * sampleCol) == lastcol
280 && (int) (row * sampleRow) == lastrow)
286 lastcol = (int) (col * sampleCol);
288 color = getColumnColourFromSequence(seq, hiddenRow,
289 hasHiddenCols, lastcol, finder);
292 if (sameCol == 1 && sameRow == 1)
294 mg.drawLine(xstart, ystart, xstart, ystart);
298 mg.fillRect(xstart, ystart, sameCol, sameRow);
305 lastrow = (int) (row * sampleRow);
313 * Find the colour of a sequence at a specified column position
315 private Color getColumnColourFromSequence(
316 jalview.datamodel.SequenceI seq, boolean hiddenRow,
317 boolean hasHiddenCols, int lastcol, FeatureColourFinder finder)
319 Color color = Color.white;
320 if (seq.getLength() > lastcol)
322 color = sr.getResidueColour(seq, lastcol, finder);
326 || (hasHiddenCols && !av.getColumnSelection()
327 .isVisible(lastcol)))
329 color = color.darker().darker();
335 * Update the overview panel box when the associated alignment panel is
339 private void setBoxPosition()
341 od.setBoxPosition(av.getAlignment()
342 .getHiddenSequences(), av.getColumnSelection(), av.getRanges());
347 public void update(Graphics g)
353 public void paint(Graphics g)
355 Graphics og = offscreen.getGraphics();
358 og.drawImage(miniMe, 0, 0, this);
359 og.setColor(Color.red);
361 g.drawImage(offscreen, 0, 0, this);
366 public void propertyChange(PropertyChangeEvent evt)