Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.gui

File IdCanvas.java

 

Coverage histogram

../../img/srcFileCovDistChart8.png
19% of files have more coverage

Code metrics

82
179
12
1
601
373
66
0.37
14.92
12
5.5

Classes

Class Line # Actions
IdCanvas 46 179 66 71
0.7399267674%
 

Contributing tests

This file is covered by 82 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
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.
11    *
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.
16    *
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.
20    */
21    package jalview.gui;
22   
23    import jalview.datamodel.SequenceI;
24    import jalview.viewmodel.ViewportListenerI;
25    import jalview.viewmodel.ViewportRanges;
26   
27    import java.awt.BorderLayout;
28    import java.awt.Color;
29    import java.awt.Font;
30    import java.awt.FontMetrics;
31    import java.awt.Graphics;
32    import java.awt.Graphics2D;
33    import java.awt.RenderingHints;
34    import java.awt.image.BufferedImage;
35    import java.beans.PropertyChangeEvent;
36    import java.util.List;
37   
38    import javax.swing.JPanel;
39   
40    /**
41    * DOCUMENT ME!
42    *
43    * @author $author$
44    * @version $Revision$
45    */
 
46    public class IdCanvas extends JPanel implements ViewportListenerI
47    {
48    protected AlignViewport av;
49   
50    protected boolean showScores = true;
51   
52    protected int maxIdLength = -1;
53   
54    protected String maxIdStr = null;
55   
56    BufferedImage image;
57   
58    Graphics2D gg;
59   
60    int imgHeight = 0;
61   
62    boolean fastPaint = false;
63   
64    List<SequenceI> searchResults;
65   
66    AnnotationPanel ap;
67   
68    private Font idfont;
69   
70    /**
71    * Creates a new IdCanvas object.
72    *
73    * @param av
74    * DOCUMENT ME!
75    */
 
76  217 toggle public IdCanvas(AlignViewport av)
77    {
78  217 setLayout(new BorderLayout());
79  217 this.av = av;
80  217 PaintRefresher.Register(this, av.getSequenceSetId());
81  217 av.getRanges().addPropertyChangeListener(this);
82    }
83   
84    /**
85    * DOCUMENT ME!
86    *
87    * @param g
88    * DOCUMENT ME!
89    * @param hiddenRows
90    * true - check and display hidden row marker if need be
91    * @param s
92    * DOCUMENT ME!
93    * @param i
94    * DOCUMENT ME!
95    * @param starty
96    * DOCUMENT ME!
97    * @param ypos
98    * DOCUMENT ME!
99    */
 
100  696 toggle public void drawIdString(Graphics2D g, boolean hiddenRows, SequenceI s,
101    int i, int starty, int ypos)
102    {
103  696 int xPos = 0;
104  696 int panelWidth = getWidth();
105  696 int charHeight = av.getCharHeight();
106   
107  696 if ((searchResults != null) && searchResults.contains(s))
108    {
109  0 g.setColor(Color.black);
110  0 g.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
111    charHeight);
112  0 g.setColor(Color.white);
113    }
114  696 else if ((av.getSelectionGroup() != null)
115    && av.getSelectionGroup().getSequences(null).contains(s))
116    {
117  0 g.setColor(Color.lightGray);
118  0 g.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
119    charHeight);
120  0 g.setColor(Color.white);
121    }
122    else
123    {
124  696 g.setColor(av.getSequenceColour(s));
125  696 g.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),
126    charHeight);
127  696 g.setColor(Color.black);
128    }
129   
130  696 if (av.isRightAlignIds())
131    {
132  0 FontMetrics fm = g.getFontMetrics();
133  0 xPos = panelWidth
134    - fm.stringWidth(s.getDisplayId(av.getShowJVSuffix())) - 4;
135    }
136   
137  696 g.drawString(s.getDisplayId(av.getShowJVSuffix()), xPos,
138    (((i - starty + 1) * charHeight) + ypos) - (charHeight / 5));
139   
140  696 if (hiddenRows)
141    {
142  696 drawMarker(g, av, i, starty, ypos);
143    }
144   
145    }
146   
147    /**
148    * DOCUMENT ME!
149    *
150    * @param vertical
151    * DOCUMENT ME!
152    */
 
153  3 toggle public void fastPaint(int vertical)
154    {
155    /*
156    * for now, not attempting fast paint of wrapped ids...
157    */
158  3 if (gg == null || av.getWrapAlignment())
159    {
160  3 repaint();
161   
162  3 return;
163    }
164   
165  0 ViewportRanges ranges = av.getRanges();
166   
167  0 gg.copyArea(0, 0, getWidth(), imgHeight, 0,
168    -vertical * av.getCharHeight());
169   
170  0 int ss = ranges.getStartSeq();
171  0 int es = ranges.getEndSeq();
172  0 int transY = 0;
173   
174  0 if (vertical > 0) // scroll down
175    {
176  0 ss = es - vertical;
177   
178  0 if (ss < ranges.getStartSeq())
179    { // ie scrolling too fast, more than a page at a time
180  0 ss = ranges.getStartSeq();
181    }
182    else
183    {
184  0 transY = imgHeight - ((vertical + 1) * av.getCharHeight());
185    }
186    }
187  0 else if (vertical < 0) // scroll up
188    {
189  0 es = ss - vertical;
190   
191  0 if (es > ranges.getEndSeq())
192    {
193  0 es = ranges.getEndSeq();
194    }
195    }
196   
197  0 gg.translate(0, transY);
198   
199  0 drawIds(gg, av, ss, es, searchResults);
200   
201  0 gg.translate(0, -transY);
202   
203  0 fastPaint = true;
204   
205    // Call repaint on alignment panel so that repaints from other alignment
206    // panel components can be aggregated. Otherwise performance of the overview
207    // window and others may be adversely affected.
208  0 av.getAlignPanel().repaint();
209    }
210   
211    /**
212    * DOCUMENT ME!
213    *
214    * @param g
215    * DOCUMENT ME!
216    */
 
217  979 toggle @Override
218    public void paintComponent(Graphics g)
219    {
220  979 super.paintComponent(g);
221   
222  979 g.setColor(Color.white);
223  979 g.fillRect(0, 0, getWidth(), getHeight());
224   
225  979 if (fastPaint)
226    {
227  0 fastPaint = false;
228  0 g.drawImage(image, 0, 0, this);
229   
230  0 return;
231    }
232   
233  979 int oldHeight = imgHeight;
234   
235  979 imgHeight = getHeight();
236  979 imgHeight -= (imgHeight % av.getCharHeight());
237   
238  979 if (imgHeight < 1)
239    {
240  0 return;
241    }
242   
243  979 if (oldHeight != imgHeight || image.getWidth(this) != getWidth())
244    {
245  102 image = new BufferedImage(getWidth(), imgHeight,
246    BufferedImage.TYPE_INT_RGB);
247    }
248   
249  979 gg = (Graphics2D) image.getGraphics();
250   
251    // Fill in the background
252  979 gg.setColor(Color.white);
253  979 gg.fillRect(0, 0, getWidth(), imgHeight);
254   
255  979 drawIds(gg, av, av.getRanges().getStartSeq(), av.getRanges().getEndSeq(), searchResults);
256   
257  979 g.drawImage(image, 0, 0, this);
258    }
259   
260    /**
261    * Draws sequence ids from sequence index startSeq to endSeq (inclusive), with
262    * the font and other display settings configured on the viewport. Ids of
263    * sequences included in the selection are coloured grey, otherwise the
264    * current id colour for the sequence id is used.
265    *
266    * @param g
267    * @param alignViewport
268    * @param startSeq
269    * @param endSeq
270    * @param selection
271    */
 
272  979 toggle void drawIds(Graphics2D g, AlignViewport alignViewport, final int startSeq,
273    final int endSeq, List<SequenceI> selection)
274    {
275  979 Font font = alignViewport.getFont();
276  979 if (alignViewport.isSeqNameItalics())
277    {
278  979 setIdfont(new Font(font.getName(), Font.ITALIC,
279    font.getSize()));
280    }
281    else
282    {
283  0 setIdfont(font);
284    }
285   
286  979 g.setFont(getIdfont());
287  979 FontMetrics fm = g.getFontMetrics();
288   
289  979 if (alignViewport.antiAlias)
290    {
291  0 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
292    RenderingHints.VALUE_ANTIALIAS_ON);
293    }
294   
295  979 Color currentColor = Color.white;
296  979 Color currentTextColor = Color.black;
297   
298  979 boolean hasHiddenRows = alignViewport.hasHiddenRows();
299   
300  979 if (alignViewport.getWrapAlignment())
301    {
302  174 drawIdsWrapped(g, alignViewport, startSeq, getHeight());
303  174 return;
304    }
305   
306    // Now draw the id strings
307  805 int panelWidth = getWidth();
308  805 int xPos = 0;
309   
310    // Now draw the id strings
311  7034 for (int i = startSeq; i <= endSeq; i++)
312    {
313  6229 SequenceI sequence = alignViewport.getAlignment().getSequenceAt(i);
314   
315  6229 if (sequence == null)
316    {
317  0 continue;
318    }
319   
320  6229 if (hasHiddenRows || alignViewport.isDisplayReferenceSeq())
321    {
322  5464 g.setFont(getHiddenFont(sequence, alignViewport));
323    }
324   
325    // Selected sequence colours
326  6229 if (selection != null && selection.contains(sequence))
327    {
328  0 currentColor = Color.black;
329  0 currentTextColor = Color.white;
330    }
331  6229 else if ((alignViewport.getSelectionGroup() != null) && alignViewport
332    .getSelectionGroup().getSequences(null).contains(sequence))
333    {
334  6 currentColor = Color.lightGray;
335  6 currentTextColor = Color.black;
336    }
337    else
338    {
339  6223 currentColor = alignViewport.getSequenceColour(sequence);
340  6223 currentTextColor = Color.black;
341    }
342   
343  6229 g.setColor(currentColor);
344   
345  6229 int charHeight = alignViewport.getCharHeight();
346  6229 g.fillRect(0, (i - startSeq) * charHeight,
347    getWidth(), charHeight);
348   
349  6229 g.setColor(currentTextColor);
350   
351  6229 String string = sequence
352    .getDisplayId(alignViewport.getShowJVSuffix());
353   
354  6229 if (alignViewport.isRightAlignIds())
355    {
356  0 xPos = panelWidth - fm.stringWidth(string) - 4;
357    }
358   
359  6229 g.drawString(string, xPos, (((i - startSeq) * charHeight) + charHeight)
360    - (charHeight / 5));
361   
362  6229 if (hasHiddenRows)
363    {
364  5464 drawMarker(g, alignViewport, i, startSeq, 0);
365    }
366    }
367    }
368   
369    /**
370    * Draws sequence ids, and annotation labels if annotations are shown, in
371    * wrapped mode
372    *
373    * @param g
374    * @param alignViewport
375    * @param startSeq
376    */
 
377  174 toggle void drawIdsWrapped(Graphics2D g, AlignViewport alignViewport,
378    int startSeq, int pageHeight)
379    {
380  174 int alignmentWidth = alignViewport.getAlignment().getWidth();
381  174 final int alheight = alignViewport.getAlignment().getHeight();
382   
383  174 if (alignViewport.hasHiddenColumns())
384    {
385  174 alignmentWidth = alignViewport.getAlignment().getHiddenColumns()
386    .absoluteToVisibleColumn(alignmentWidth) - 1;
387    }
388   
389  174 int annotationHeight = 0;
390   
391  174 AnnotationLabels labels = null;
392  174 if (alignViewport.isShowAnnotation())
393    {
394  174 if (ap == null)
395    {
396  12 ap = new AnnotationPanel(alignViewport);
397    }
398  174 annotationHeight = ap.adjustPanelHeight();
399  174 labels = new AnnotationLabels(alignViewport);
400    }
401   
402  174 final int charHeight = alignViewport.getCharHeight();
403  174 int hgap = charHeight;
404  174 if (alignViewport.getScaleAboveWrapped())
405    {
406  0 hgap += charHeight;
407    }
408   
409    /*
410    * height of alignment + gap + annotations (if shown)
411    */
412  174 int cHeight = alheight * charHeight + hgap
413    + annotationHeight;
414   
415  174 ViewportRanges ranges = alignViewport.getRanges();
416   
417  174 int rowSize = ranges.getViewportWidth();
418   
419    /*
420    * draw repeating sequence ids until out of sequence data or
421    * out of visible space, whichever comes first
422    */
423  174 boolean hasHiddenRows = alignViewport.hasHiddenRows();
424  174 int ypos = hgap;
425  174 int rowStartRes = ranges.getStartRes();
426  522 while ((ypos <= pageHeight) && (rowStartRes < alignmentWidth))
427    {
428  1044 for (int i = startSeq; i < alheight; i++)
429    {
430  696 SequenceI s = alignViewport.getAlignment().getSequenceAt(i);
431  696 if (hasHiddenRows || alignViewport.isDisplayReferenceSeq())
432    {
433  696 g.setFont(getHiddenFont(s, alignViewport));
434    }
435    else
436    {
437  0 g.setFont(getIdfont());
438    }
439  696 drawIdString(g, hasHiddenRows, s, i, 0, ypos);
440    }
441   
442  348 if (labels != null && alignViewport.isShowAnnotation())
443    {
444  348 g.translate(0, ypos + (alheight * charHeight));
445  348 labels.drawComponent(g, getWidth());
446  348 g.translate(0, -ypos - (alheight * charHeight));
447    }
448   
449  348 ypos += cHeight;
450  348 rowStartRes += rowSize;
451    }
452    }
453   
454    /**
455    * Draws a marker (a blue right-pointing triangle) between sequences to
456    * indicate hidden sequences.
457    *
458    * @param g
459    * @param alignViewport
460    * @param seqIndex
461    * @param starty
462    * @param yoffset
463    */
 
464  6160 toggle void drawMarker(Graphics2D g, AlignViewport alignViewport, int seqIndex, int starty, int yoffset)
465    {
466  6160 SequenceI[] hseqs = alignViewport.getAlignment()
467    .getHiddenSequences().hiddenSequences;
468    // Use this method here instead of calling hiddenSeq adjust
469    // 3 times.
470  6160 int hSize = hseqs.length;
471   
472  6160 int hiddenIndex = seqIndex;
473  6160 int lastIndex = seqIndex - 1;
474  6160 int nextIndex = seqIndex + 1;
475   
476  104720 for (int j = 0; j < hSize; j++)
477    {
478  98560 if (hseqs[j] != null)
479    {
480  16918 if (j - 1 < hiddenIndex)
481    {
482  196 hiddenIndex++;
483    }
484  16918 if (j - 1 < lastIndex)
485    {
486  161 lastIndex++;
487    }
488  16918 if (j - 1 < nextIndex)
489    {
490  5110 nextIndex++;
491    }
492    }
493    }
494   
495    /*
496    * are we below or above the hidden sequences?
497    */
498  6160 boolean below = (hiddenIndex > lastIndex + 1);
499  6160 boolean above = (nextIndex > hiddenIndex + 1);
500   
501  6160 g.setColor(Color.blue);
502  6160 int charHeight = av.getCharHeight();
503   
504    /*
505    * vertices of the triangle, below or above hidden seqs
506    */
507  6160 int[] xPoints = new int[]
508    { getWidth() - charHeight,
509    getWidth() - charHeight, getWidth() };
510  6160 int yShift = seqIndex - starty;
511   
512  6160 if (below)
513    {
514  21 int[] yPoints = new int[] { yShift * charHeight + yoffset,
515    yShift * charHeight + yoffset + charHeight / 4,
516    yShift * charHeight + yoffset };
517  21 g.fillPolygon(xPoints, yPoints, 3);
518    }
519  6160 if (above)
520    {
521  376 yShift++;
522  376 int[] yPoints = new int[] { yShift * charHeight + yoffset,
523    yShift * charHeight + yoffset - charHeight / 4,
524    yShift * charHeight + yoffset };
525  376 g.fillPolygon(xPoints, yPoints, 3);
526    }
527    }
528   
529    /**
530    * Answers the standard sequence id font, or a bold font if the sequence is
531    * set as reference or a hidden group representative
532    *
533    * @param seq
534    * @param alignViewport
535    * @return
536    */
 
537  6160 toggle private Font getHiddenFont(SequenceI seq, AlignViewport alignViewport)
538    {
539  6160 if (av.isReferenceSeq(seq) || av.isHiddenRepSequence(seq))
540    {
541  76 return new Font(av.getFont().getName(), Font.BOLD,
542    av.getFont().getSize());
543    }
544  6084 return getIdfont();
545    }
546   
547    /**
548    * DOCUMENT ME!
549    *
550    * @param list
551    * DOCUMENT ME!
552    */
 
553  0 toggle public void setHighlighted(List<SequenceI> list)
554    {
555  0 searchResults = list;
556  0 repaint();
557    }
558   
 
559  7063 toggle public Font getIdfont()
560    {
561  7063 return idfont;
562    }
563   
 
564  979 toggle public void setIdfont(Font idfont)
565    {
566  979 this.idfont = idfont;
567    }
568   
569    /**
570    * Respond to viewport range changes (e.g. alignment panel was scrolled). Both
571    * scrolling and resizing change viewport ranges. Scrolling changes both start
572    * and end points, but resize only changes end values. Here we only want to
573    * fastpaint on a scroll, with resize using a normal paint, so scroll events
574    * are identified as changes to the horizontal or vertical start value.
575    * <p>
576    * In unwrapped mode, only responds to a vertical scroll, as horizontal scroll
577    * leaves sequence ids unchanged. In wrapped mode, only vertical scroll is
578    * provided, but it generates a change of "startres" which does require an
579    * update here.
580    */
 
581  452 toggle @Override
582    public void propertyChange(PropertyChangeEvent evt)
583    {
584  452 String propertyName = evt.getPropertyName();
585  452 if (propertyName.equals(ViewportRanges.STARTSEQ)
586    || (av.getWrapAlignment()
587    && propertyName.equals(ViewportRanges.STARTRES)))
588    {
589  3 fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
590    }
591  449 else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ))
592    {
593  0 fastPaint(((int[]) evt.getNewValue())[1]
594    - ((int[]) evt.getOldValue())[1]);
595    }
596  449 else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT))
597    {
598  0 repaint();
599    }
600    }
601    }