3 import jalview.api.AlignViewportI;
4 import jalview.datamodel.SequenceI;
5 import jalview.renderer.AnnotationRenderer;
6 import jalview.viewmodel.OverviewDimensions;
9 import java.awt.Dimension;
10 import java.awt.Graphics;
11 import java.awt.image.BufferedImage;
13 import javax.swing.JComponent;
15 public class OverviewCanvas extends JComponent
17 private static final Color TRANS_GREY = new Color(100, 100, 100, 25);
19 private BufferedImage miniMe;
21 private BufferedImage lastMiniMe = null;
23 public boolean updating = false;
25 // This is set true if the user resizes whilst
26 // the overview is being calculated
27 public volatile boolean updateAgain = false;
29 // Can set different properties in this seqCanvas than
30 // main visible SeqCanvas
31 private SequenceRenderer sr;
33 private jalview.renderer.seqfeatures.FeatureRenderer fr;
35 private final AnnotationRenderer renderer = new AnnotationRenderer();
37 OverviewDimensions od;
45 public OverviewCanvas(OverviewDimensions overviewDims,
46 AlignViewportI alignvp, AlignmentPanel alignp, OverviewPanel overp)
53 sr = new SequenceRenderer(av);
54 sr.renderGaps = false;
55 sr.forOverview = true;
56 fr = new FeatureRenderer(ap);
59 public void draw(boolean showSequenceFeatures, boolean showAnnotation)
63 if (showSequenceFeatures)
65 fr.transferSettings(ap.getSeqPanel().seqCanvas.getFeatureRenderer());
68 // why do we need to set preferred size again? was set in
69 // updateOverviewImage
70 setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
72 miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
73 BufferedImage.TYPE_INT_RGB);
75 Graphics mg = miniMe.getGraphics();
76 mg.setColor(Color.orange);
77 mg.fillRect(0, 0, od.getWidth(), miniMe.getHeight());
79 // calculate sampleCol and sampleRow
80 // alignment width is max number of residues/bases
81 // alignment height is number of sequences
82 int alwidth = av.getAlignment().getWidth();
83 int alheight = av.getAlignment().getAbsoluteHeight();
85 // sampleCol or sampleRow is the width/height allocated to each residue
86 // in particular, sometimes we may need more than one row/col of the
87 // BufferedImage allocated
88 // sampleCol is how much of a residue to assign to each pixel
89 // sampleRow is how many sequences to assign to each pixel
90 float sampleCol = alwidth / (float) od.getWidth();
91 float sampleRow = alheight / (float) od.getSequencesHeight();
93 buildImage(sampleRow, sampleCol);
97 renderer.updateFromAlignViewport(av);
98 for (int col = 0; col < od.getWidth() && !updateAgain; col++)
100 mg.translate(col, od.getSequencesHeight());
101 renderer.drawGraph(mg, av.getAlignmentConservationAnnotation(),
102 av.getAlignmentConservationAnnotation().annotations,
103 (int) (sampleCol) + 1, od.getGraphHeight(),
104 (int) (col * sampleCol), (int) (col * sampleCol) + 1);
105 mg.translate(-col, -od.getSequencesHeight());
116 op.updateOverviewImage();
125 public void paintComponent(Graphics g)
127 if (updating || updateAgain)
129 if (lastMiniMe == null)
131 g.setColor(Color.white);
132 g.fillRect(0, 0, getWidth(), getHeight());
136 g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
138 g.setColor(TRANS_GREY);
139 g.fillRect(0, 0, getWidth(), getHeight());
141 else if (lastMiniMe != null)
143 g.drawImage(lastMiniMe, 0, 0, this);
144 if (lastMiniMe != miniMe)
146 g.setColor(TRANS_GREY);
147 g.fillRect(0, 0, getWidth(), getHeight());
151 g.setColor(Color.red);
156 * Build the overview panel image
158 private void buildImage(float sampleRow, float sampleCol)
162 int color = Color.white.getRGB();
164 SequenceI seq = null;
166 final boolean hasHiddenCols = av.hasHiddenColumns();
167 boolean hiddenRow = false;
168 // get hidden row and hidden column map once at beginning.
169 // clone featureRenderer settings to avoid race conditions... if state is
170 // updated just need to refresh again
171 for (int row = 0; row < od.getSequencesHeight() && !updateAgain; row++)
173 boolean doCopy = true;
174 int currentrow = (int) (row * sampleRow);
175 if (currentrow != lastrow)
179 lastrow = currentrow;
181 // get the sequence which would be at alignment index 'lastrow' if no
182 // rows were hidden, and determine whether it is hidden or not
183 hiddenRow = av.getAlignment().isHidden(lastrow);
184 seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
187 for (int col = 0; col < od.getWidth() && !updateAgain; col++)
191 color = miniMe.getRGB(col, row - 1);
193 else if ((int) (col * sampleCol) != lastcol
194 || (int) (row * sampleRow) != lastrow)
196 lastcol = (int) (col * sampleCol);
197 color = getColumnColourFromSequence(seq, hiddenRow,
198 hasHiddenCols, lastcol);
200 // else we just use the color we already have , so don't need to set it
202 miniMe.setRGB(col, row, color);
208 * Find the colour of a sequence at a specified column position
210 private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq,
211 boolean hiddenRow, boolean hasHiddenCols, int lastcol)
217 color = Color.white.getRGB();
219 else if (seq.getLength() > lastcol)
221 color = sr.getResidueBoxColour(seq, lastcol).getRGB();
223 if (av.isShowSequenceFeatures())
225 color = fr.findFeatureColour(color, seq, lastcol);
230 color = Color.white.getRGB();
234 || (hasHiddenCols && !av.getColumnSelection()
235 .isVisible(lastcol)))
237 color = new Color(color).darker().darker().getRGB();