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.renderer;
23 import jalview.api.AlignmentColsCollectionI;
24 import jalview.api.AlignmentRowsCollectionI;
25 import jalview.api.RendererListenerI;
26 import jalview.datamodel.AlignmentAnnotation;
27 import jalview.datamodel.Annotation;
28 import jalview.datamodel.SequenceI;
29 import jalview.renderer.seqfeatures.FeatureColourFinder;
30 import jalview.renderer.seqfeatures.FeatureRenderer;
31 import jalview.viewmodel.OverviewDimensions;
33 import java.awt.Color;
34 import java.awt.Graphics;
35 import java.awt.image.BufferedImage;
36 import java.beans.PropertyChangeSupport;
38 public class OverviewRenderer
40 public static final String UPDATE = "OverviewUpdate";
42 private static final int MAX_PROGRESS = 100;
44 private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
47 private FeatureColourFinder finder;
49 private jalview.api.SequenceRenderer sr;
52 private BufferedImage miniMe;
54 // raw number of pixels to allocate to each column
55 private float pixelsPerCol;
57 // raw number of pixels to allocate to each row
58 private float pixelsPerSeq;
60 // height in pixels of graph
61 private int graphHeight;
63 // flag to indicate whether to halt drawing
64 private volatile boolean redraw = false;
66 public OverviewRenderer(jalview.api.SequenceRenderer seqRenderer,
67 FeatureRenderer fr, OverviewDimensions od)
70 finder = new FeatureColourFinder(fr);
72 pixelsPerCol = od.getPixelsPerCol();
73 pixelsPerSeq = od.getPixelsPerSeq();
74 graphHeight = od.getGraphHeight();
75 miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
76 BufferedImage.TYPE_INT_RGB);
80 * Draw alignment rows and columns onto an image
83 * Iterator over rows to be drawn
85 * Iterator over columns to be drawn
86 * @return image containing the drawing
88 public BufferedImage draw(AlignmentRowsCollectionI rows,
89 AlignmentColsCollectionI cols)
91 int rgbcolor = Color.white.getRGB();
94 int alignmentHeight = miniMe.getHeight() - graphHeight;
95 int totalPixels = miniMe.getWidth() * alignmentHeight;
97 int lastRowUpdate = 0;
98 changeSupport.firePropertyChange(UPDATE, -1, 0);
100 for (int alignmentRow : rows)
107 // get details of this alignment row
108 boolean hidden = rows.isHidden(alignmentRow);
109 SequenceI seq = rows.getSequence(alignmentRow);
111 // calculate where this row extends to in pixels
112 int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
113 miniMe.getHeight() - 1);
117 for (int alignmentCol : cols)
124 // calculate where this column extends to in pixels
125 int endCol = Math.min(
126 Math.round((colIndex + 1) * pixelsPerCol) - 1,
127 miniMe.getWidth() - 1);
129 // don't do expensive colour determination if we're not going to use it
130 // NB this is important to avoid performance issues in the overview
132 if (pixelCol <= endCol)
134 // determine the colour based on the sequence and column position
135 rgbcolor = getColumnColourFromSequence(seq,
136 hidden || cols.isHidden(alignmentCol), alignmentCol,
139 // fill in the appropriate number of pixels
140 for (int row = pixelRow; row <= endRow; ++row)
142 for (int col = pixelCol; col <= endCol; ++col)
144 miniMe.setRGB(col, row, rgbcolor);
148 sendProgressUpdate((pixelCol + 1) * (endRow - pixelRow),
149 totalPixels, lastRowUpdate);
150 pixelCol = endCol + 1;
155 if (pixelRow != endRow + 1)
157 lastRowUpdate = sendProgressUpdate(endRow + 1, alignmentHeight, 0);
158 pixelRow = endRow + 1;
163 // final update to progress bar if present
166 sendProgressUpdate(pixelRow - 1, alignmentHeight, 0);
170 sendProgressUpdate(alignmentHeight, miniMe.getHeight(), 0);
176 * Calculate progress update value and fire event
178 private int sendProgressUpdate(int position, int maximum, int offset)
180 int newUpdate = offset
181 + Math.round(MAX_PROGRESS * ((float) position / maximum));
182 if (newUpdate > offset)
184 changeSupport.firePropertyChange(UPDATE, offset, newUpdate);
191 * Find the colour of a sequence at a specified column position
193 private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq,
194 boolean isHidden, int lastcol, FeatureColourFinder fcfinder)
196 Color color = Color.white;
198 if ((seq != null) && (seq.getLength() > lastcol))
200 color = sr.getResidueColour(seq, lastcol, fcfinder);
205 color = color.darker().darker();
208 return color.getRGB();
212 * Draw the alignment annotation in the overview panel
215 * the graphics object to draw on
217 * alignment annotation information
219 * alignment character width value
221 * y-position for the annotation graph
223 * the collection of columns used in the overview panel
225 public void drawGraph(Graphics g, AlignmentAnnotation anno, int charWidth,
226 int y, AlignmentColsCollectionI cols)
228 Annotation[] annotations = anno.annotations;
229 g.setColor(Color.white);
230 g.fillRect(0, 0, miniMe.getWidth(), y);
235 for (int alignmentCol : cols)
239 changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1, 0);
243 if (alignmentCol >= annotations.length)
245 break; // no more annotations to draw here
249 int endCol = Math.min(
250 Math.round((colIndex + 1) * pixelsPerCol) - 1,
251 miniMe.getWidth() - 1);
253 if (annotations[alignmentCol] != null)
255 if (annotations[alignmentCol].colour == null)
257 g.setColor(Color.black);
261 g.setColor(annotations[alignmentCol].colour);
264 height = (int) ((annotations[alignmentCol].value / anno.graphMax) * y);
270 g.fillRect(pixelCol, y - height, endCol - pixelCol + 1, height);
273 pixelCol = endCol + 1;
277 changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1,
281 public void setRedraw(boolean b)
289 public void addPropertyChangeListener(RendererListenerI listener)
291 changeSupport.addPropertyChangeListener(listener);
294 public void removePropertyChangeListener(RendererListenerI listener)
296 changeSupport.removePropertyChangeListener(listener);