3 import jalview.api.AlignViewportI;
4 import jalview.datamodel.SequenceI;
5 import jalview.renderer.AnnotationRenderer;
6 import jalview.renderer.seqfeatures.FeatureColourFinder;
7 import jalview.viewmodel.OverviewDimensions;
10 import java.awt.Dimension;
11 import java.awt.Graphics;
12 import java.awt.image.BufferedImage;
14 import javax.swing.JComponent;
16 public class OverviewCanvas extends JComponent
18 private static final Color TRANS_GREY = new Color(100, 100, 100, 25);
20 private BufferedImage miniMe;
22 private BufferedImage lastMiniMe = null;
24 public boolean updating = false;
26 // This is set true if the user resizes whilst
27 // the overview is being calculated
28 public volatile boolean updateAgain = false;
30 // Can set different properties in this seqCanvas than
31 // main visible SeqCanvas
32 private SequenceRenderer sr;
34 private jalview.renderer.seqfeatures.FeatureRenderer fr;
36 private final AnnotationRenderer renderer = new AnnotationRenderer();
38 OverviewDimensions od;
46 public OverviewCanvas(OverviewDimensions overviewDims,
47 AlignViewportI alignvp, AlignmentPanel alignp, OverviewPanel overp)
54 sr = new SequenceRenderer(av);
55 sr.renderGaps = false;
56 sr.forOverview = true;
57 fr = new FeatureRenderer(ap);
60 public void draw(boolean showSequenceFeatures, boolean showAnnotation)
64 if (showSequenceFeatures)
66 fr.transferSettings(ap.getSeqPanel().seqCanvas.getFeatureRenderer());
69 // why do we need to set preferred size again? was set in
70 // updateOverviewImage
71 setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
73 miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
74 BufferedImage.TYPE_INT_RGB);
76 Graphics mg = miniMe.getGraphics();
77 mg.setColor(Color.orange);
78 mg.fillRect(0, 0, od.getWidth(), miniMe.getHeight());
80 // calculate sampleCol and sampleRow
81 // alignment width is max number of residues/bases
82 // alignment height is number of sequences
83 int alwidth = av.getAlignment().getWidth();
84 int alheight = av.getAlignment().getAbsoluteHeight();
86 // sampleCol or sampleRow is the width/height allocated to each residue
87 // in particular, sometimes we may need more than one row/col of the
88 // BufferedImage allocated
89 // sampleCol is how much of a residue to assign to each pixel
90 // sampleRow is how many sequences to assign to each pixel
91 float sampleCol = alwidth / (float) od.getWidth();
92 float sampleRow = alheight / (float) od.getSequencesHeight();
94 buildImage(sampleRow, sampleCol);
98 renderer.updateFromAlignViewport(av);
99 for (int col = 0; col < od.getWidth() && !updateAgain; col++)
101 mg.translate(col, od.getSequencesHeight());
102 renderer.drawGraph(mg, av.getAlignmentConservationAnnotation(),
103 av.getAlignmentConservationAnnotation().annotations,
104 (int) (sampleCol) + 1, od.getGraphHeight(),
105 (int) (col * sampleCol), (int) (col * sampleCol) + 1);
106 mg.translate(-col, -od.getSequencesHeight());
117 op.updateOverviewImage();
126 public void paintComponent(Graphics g)
128 if (updating || updateAgain)
130 if (lastMiniMe == null)
132 g.setColor(Color.white);
133 g.fillRect(0, 0, getWidth(), getHeight());
137 g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
139 g.setColor(TRANS_GREY);
140 g.fillRect(0, 0, getWidth(), getHeight());
142 else if (lastMiniMe != null)
144 g.drawImage(lastMiniMe, 0, 0, this);
145 if (lastMiniMe != miniMe)
147 g.setColor(TRANS_GREY);
148 g.fillRect(0, 0, getWidth(), getHeight());
152 g.setColor(Color.red);
157 * Build the overview panel image
159 private void buildImage(float sampleRow, float sampleCol)
163 int rgbcolor = Color.white.getRGB();
165 SequenceI seq = null;
166 FeatureColourFinder finder = new FeatureColourFinder(fr);
168 final boolean hasHiddenCols = av.hasHiddenColumns();
169 boolean hiddenRow = false;
170 // get hidden row and hidden column map once at beginning.
171 // clone featureRenderer settings to avoid race conditions... if state is
172 // updated just need to refresh again
173 for (int row = 0; row < od.getSequencesHeight() && !updateAgain; row++)
175 boolean doCopy = true;
176 int currentrow = (int) (row * sampleRow);
177 if (currentrow != lastrow)
181 lastrow = currentrow;
183 // get the sequence which would be at alignment index 'lastrow' if no
184 // rows were hidden, and determine whether it is hidden or not
185 hiddenRow = av.getAlignment().isHidden(lastrow);
186 seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
189 for (int col = 0; col < od.getWidth() && !updateAgain; col++)
193 rgbcolor = miniMe.getRGB(col, row - 1);
195 else if ((int) (col * sampleCol) != lastcol
196 || (int) (row * sampleRow) != lastrow)
198 lastcol = (int) (col * sampleCol);
199 rgbcolor = getColumnColourFromSequence(seq, hiddenRow,
200 hasHiddenCols, lastcol, finder);
202 // else we just use the color we already have , so don't need to set it
204 miniMe.setRGB(col, row, rgbcolor);
210 * Find the colour of a sequence at a specified column position
212 private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq,
213 boolean hiddenRow, boolean hasHiddenCols, int lastcol,
214 FeatureColourFinder finder)
216 Color color = Color.white;
218 if ((seq != null) && (seq.getLength() > lastcol))
220 color = sr.getResidueColour(seq, lastcol, finder);
224 || (hasHiddenCols && !av.getColumnSelection()
225 .isVisible(lastcol)))
227 color = color.darker().darker();
230 return color.getRGB();