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;
99 changeSupport.firePropertyChange(UPDATE, -1, 0);
101 for (int alignmentRow : rows)
108 // get details of this alignment row
109 boolean hidden = rows.isHidden(alignmentRow);
110 SequenceI seq = rows.getSequence(alignmentRow);
112 // calculate where this row extends to in pixels
113 int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
114 miniMe.getHeight() - 1);
118 for (int alignmentCol : cols)
125 // calculate where this column extends to in pixels
126 int endCol = Math.min(
127 Math.round((colIndex + 1) * pixelsPerCol) - 1,
128 miniMe.getWidth() - 1);
130 // don't do expensive colour determination if we're not going to use it
131 // NB this is important to avoid performance issues in the overview
133 if (pixelCol <= endCol)
135 // determine the colour based on the sequence and column position
136 rgbcolor = getColumnColourFromSequence(seq,
137 hidden || cols.isHidden(alignmentCol), alignmentCol,
140 // fill in the appropriate number of pixels
141 for (int row = pixelRow; row <= endRow; ++row)
143 for (int col = pixelCol; col <= endCol; ++col)
145 miniMe.setRGB(col, row, rgbcolor);
149 // store last update value
150 lastUpdate = sendProgressUpdate(
151 (pixelCol + 1) * (endRow - pixelRow), totalPixels,
152 lastRowUpdate, lastUpdate);
153 pixelCol = endCol + 1;
158 if (pixelRow != endRow + 1)
160 // store row offset and last update value
161 lastRowUpdate = sendProgressUpdate(endRow + 1, alignmentHeight, 0,
163 lastUpdate = lastRowUpdate;
164 pixelRow = endRow + 1;
169 // final update to progress bar if present
172 sendProgressUpdate(pixelRow - 1, alignmentHeight, 0, 0);
176 sendProgressUpdate(alignmentHeight, miniMe.getHeight(), 0, 0);
182 * Calculate progress update value and fire event
183 * @param rowOffset number of rows to offset calculation by
184 * @return new rowOffset - return value only to be used when at end of a row
186 private int sendProgressUpdate(int position, int maximum, int rowOffset,
189 int newUpdate = rowOffset
190 + Math.round(MAX_PROGRESS * ((float) position / maximum));
191 if (newUpdate > lastUpdate)
193 changeSupport.firePropertyChange(UPDATE, rowOffset, newUpdate);
200 * Find the colour of a sequence at a specified column position
202 private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq,
203 boolean isHidden, int lastcol, FeatureColourFinder fcfinder)
205 Color color = Color.white;
207 if ((seq != null) && (seq.getLength() > lastcol))
209 color = sr.getResidueColour(seq, lastcol, fcfinder);
214 color = color.darker().darker();
217 return color.getRGB();
221 * Draw the alignment annotation in the overview panel
224 * the graphics object to draw on
226 * alignment annotation information
228 * alignment character width value
230 * y-position for the annotation graph
232 * the collection of columns used in the overview panel
234 public void drawGraph(Graphics g, AlignmentAnnotation anno, int charWidth,
235 int y, AlignmentColsCollectionI cols)
237 Annotation[] annotations = anno.annotations;
238 g.setColor(Color.white);
239 g.fillRect(0, 0, miniMe.getWidth(), y);
244 for (int alignmentCol : cols)
248 changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1, 0);
252 if (alignmentCol >= annotations.length)
254 break; // no more annotations to draw here
258 int endCol = Math.min(
259 Math.round((colIndex + 1) * pixelsPerCol) - 1,
260 miniMe.getWidth() - 1);
262 if (annotations[alignmentCol] != null)
264 if (annotations[alignmentCol].colour == null)
266 g.setColor(Color.black);
270 g.setColor(annotations[alignmentCol].colour);
273 height = (int) ((annotations[alignmentCol].value / anno.graphMax) * y);
279 g.fillRect(pixelCol, y - height, endCol - pixelCol + 1, height);
282 pixelCol = endCol + 1;
286 changeSupport.firePropertyChange(UPDATE, MAX_PROGRESS - 1,
290 public void setRedraw(boolean b)
298 public void addPropertyChangeListener(RendererListenerI listener)
300 changeSupport.addPropertyChangeListener(listener);
303 public void removePropertyChangeListener(RendererListenerI listener)
305 changeSupport.removePropertyChangeListener(listener);