Clover icon

Coverage Report

  1. Project Clover database Wed Nov 13 2024 16:21:17 GMT
  2. Package jalview.appletgui

File IdCanvas.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
59% of files have more coverage

Code metrics

72
154
11
1
455
334
58
0.38
14
11
5.27

Classes

Class Line # Actions
IdCanvas 35 154 58
0.00%
 

Contributing tests

No tests hitting this source file were found.

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.appletgui;
22   
23    import jalview.datamodel.SequenceI;
24    import jalview.viewmodel.ViewportListenerI;
25    import jalview.viewmodel.ViewportRanges;
26   
27    import java.awt.Color;
28    import java.awt.Font;
29    import java.awt.Graphics;
30    import java.awt.Image;
31    import java.awt.Panel;
32    import java.beans.PropertyChangeEvent;
33    import java.util.List;
34   
 
35    public class IdCanvas extends Panel implements ViewportListenerI
36    {
37    protected AlignViewport av;
38   
39    protected boolean showScores = true;
40   
41    protected int maxIdLength = -1;
42   
43    protected String maxIdStr = null;
44   
45    Image image;
46   
47    Graphics gg;
48   
49    int imgHeight = 0;
50   
51    boolean fastPaint = false;
52   
53    List<SequenceI> searchResults;
54   
 
55  0 toggle public IdCanvas(AlignViewport av)
56    {
57  0 setLayout(null);
58  0 this.av = av;
59  0 PaintRefresher.Register(this, av.getSequenceSetId());
60  0 av.getRanges().addPropertyChangeListener(this);
61    }
62   
 
63  0 toggle public void drawIdString(Graphics gg, boolean hiddenRows, SequenceI s,
64    int i, int starty, int ypos)
65    {
66  0 int charHeight = av.getCharHeight();
67   
68  0 if (searchResults != null && searchResults.contains(s))
69    {
70  0 gg.setColor(Color.black);
71  0 gg.fillRect(0, ((i - starty) * charHeight) + ypos, getSize().width,
72    charHeight);
73  0 gg.setColor(Color.white);
74    }
75  0 else if (av.getSelectionGroup() != null
76    && av.getSelectionGroup().getSequences(null).contains(s))
77    {
78  0 gg.setColor(Color.lightGray);
79  0 gg.fillRect(0, ((i - starty) * charHeight) + ypos, getSize().width,
80    charHeight);
81  0 gg.setColor(Color.white);
82    }
83    else
84    {
85  0 gg.setColor(av.getSequenceColour(s));
86  0 gg.fillRect(0, ((i - starty) * charHeight) + ypos, getSize().width,
87    charHeight);
88  0 gg.setColor(Color.black);
89    }
90   
91  0 gg.drawString(s.getDisplayId(av.getShowJVSuffix()), 0,
92    ((i - starty) * charHeight) + ypos + charHeight
93    - (charHeight / 5));
94   
95  0 if (hiddenRows)
96    {
97  0 drawMarker(i, starty, ypos);
98    }
99   
100    }
101   
 
102  0 toggle public void fastPaint(int vertical)
103    {
104  0 if (gg == null || av.getWrapAlignment())
105    {
106  0 repaint();
107  0 return;
108    }
109   
110  0 ViewportRanges ranges = av.getRanges();
111   
112  0 gg.copyArea(0, 0, getSize().width, imgHeight, 0,
113    -vertical * av.getCharHeight());
114   
115  0 int ss = ranges.getStartSeq(), es = ranges.getEndSeq(), transY = 0;
116  0 if (vertical > 0) // scroll down
117    {
118  0 ss = es - vertical;
119  0 if (ss < ranges.getStartSeq()) // ie scrolling too fast, more than a page
120    // at a
121    // time
122    {
123  0 ss = ranges.getStartSeq();
124    }
125    else
126    {
127  0 transY = imgHeight - ((vertical + 1) * av.getCharHeight());
128    }
129    }
130  0 else if (vertical < 0)
131    {
132  0 es = ss - vertical;
133  0 if (es > ranges.getEndSeq())
134    {
135  0 es = ranges.getEndSeq();
136    }
137    }
138   
139  0 gg.translate(0, transY);
140   
141  0 drawIds(ss, es);
142   
143  0 gg.translate(0, -transY);
144   
145  0 fastPaint = true;
146  0 repaint();
147    }
148   
 
149  0 toggle @Override
150    public void update(Graphics g)
151    {
152  0 paint(g);
153    }
154   
 
155  0 toggle @Override
156    public void paint(Graphics g)
157    {
158  0 if (getSize().height < 0 || getSize().width < 0)
159    {
160  0 return;
161    }
162  0 if (fastPaint)
163    {
164  0 fastPaint = false;
165  0 g.drawImage(image, 0, 0, this);
166  0 return;
167    }
168   
169  0 imgHeight = getSize().height;
170  0 imgHeight -= imgHeight % av.getCharHeight();
171   
172  0 if (imgHeight < 1)
173    {
174  0 return;
175    }
176   
177  0 if (image == null || imgHeight != image.getHeight(this))
178    {
179  0 image = createImage(getSize().width, imgHeight);
180  0 gg = image.getGraphics();
181  0 gg.setFont(av.getFont());
182    }
183   
184    // Fill in the background
185  0 gg.setColor(Color.white);
186  0 Font italic = new Font(av.getFont().getName(), Font.ITALIC,
187    av.getFont().getSize());
188  0 gg.setFont(italic);
189   
190  0 gg.fillRect(0, 0, getSize().width, getSize().height);
191  0 drawIds(av.getRanges().getStartSeq(), av.getRanges().getEndSeq());
192  0 g.drawImage(image, 0, 0, this);
193    }
194   
195    /**
196    * local copy of av.getCharHeight set at top of drawIds
197    */
198    private int avcharHeight;
199   
 
200  0 toggle void drawIds(int starty, int endy)
201    {
202  0 avcharHeight = av.getCharHeight();
203   
204  0 Color currentColor = Color.white;
205  0 Color currentTextColor = Color.black;
206   
207  0 final boolean doHiddenCheck = av.isDisplayReferenceSeq()
208    || av.hasHiddenRows();
209  0 boolean hiddenRows = av.hasHiddenRows() && av.getShowHiddenMarkers();
210   
211  0 if (av.getWrapAlignment())
212    {
213  0 drawIdsWrapped(starty, doHiddenCheck, hiddenRows);
214  0 return;
215    }
216   
217    // Now draw the id strings
218  0 SequenceI seq;
219  0 for (int i = starty; i <= endy; i++)
220    {
221  0 seq = av.getAlignment().getSequenceAt(i);
222  0 if (seq == null)
223    {
224  0 continue;
225    }
226    // hardwired italic IDs in applet currently
227  0 Font italic = new Font(av.getFont().getName(), Font.ITALIC,
228    av.getFont().getSize());
229  0 gg.setFont(italic);
230    // boolean isrep=false;
231  0 if (doHiddenCheck)
232    {
233    // isrep =
234  0 setHiddenFont(seq);
235    }
236   
237    // Selected sequence colours
238  0 if ((searchResults != null) && searchResults.contains(seq))
239    {
240  0 currentColor = Color.black;
241  0 currentTextColor = Color.white;
242    }
243  0 else if ((av.getSelectionGroup() != null)
244    && av.getSelectionGroup().getSequences(null).contains(seq))
245    {
246  0 currentColor = Color.lightGray;
247  0 currentTextColor = Color.black;
248    }
249    else
250    {
251  0 currentColor = av.getSequenceColour(seq);
252  0 currentTextColor = Color.black;
253    }
254   
255  0 gg.setColor(currentColor);
256    // TODO: isrep could be used to highlight the representative in a
257    // different way
258  0 gg.fillRect(0, (i - starty) * avcharHeight, getSize().width,
259    avcharHeight);
260  0 gg.setColor(currentTextColor);
261   
262  0 gg.drawString(seq.getDisplayId(av.getShowJVSuffix()), 0,
263    (((i - starty) * avcharHeight) + avcharHeight)
264    - (avcharHeight / 5));
265   
266  0 if (hiddenRows)
267    {
268  0 drawMarker(i, starty, 0);
269    }
270    }
271    }
272   
273    /**
274    * Draws sequence ids in wrapped mode
275    *
276    * @param starty
277    * @param doHiddenCheck
278    * @param hiddenRows
279    */
 
280  0 toggle protected void drawIdsWrapped(int starty, final boolean doHiddenCheck,
281    boolean hiddenRows)
282    {
283  0 int maxwidth = av.getAlignment().getVisibleWidth();
284  0 int alheight = av.getAlignment().getHeight();
285   
286  0 int annotationHeight = 0;
287  0 AnnotationLabels labels = null;
288   
289  0 if (av.isShowAnnotation())
290    {
291  0 AnnotationPanel ap = new AnnotationPanel(av);
292  0 annotationHeight = ap.adjustPanelHeight();
293  0 labels = new AnnotationLabels(av);
294    }
295  0 int hgap = avcharHeight;
296  0 if (av.getScaleAboveWrapped())
297    {
298  0 hgap += avcharHeight;
299    }
300   
301  0 int cHeight = alheight * avcharHeight + hgap + annotationHeight;
302   
303  0 int rowSize = av.getRanges().getViewportWidth();
304   
305    // hardwired italic IDs in applet currently
306  0 Font italic = new Font(av.getFont().getName(), Font.ITALIC,
307    av.getFont().getSize());
308  0 gg.setFont(italic);
309   
310    /*
311    * draw repeating sequence ids until out of sequence data or
312    * out of visible space, whichever comes first
313    */
314  0 int ypos = hgap;
315  0 int row = av.getRanges().getStartRes();
316  0 while ((ypos <= getHeight()) && (row < maxwidth))
317    {
318  0 for (int i = starty; i < alheight; i++)
319    {
320   
321  0 SequenceI s = av.getAlignment().getSequenceAt(i);
322    // gg.setFont(italic);
323  0 if (doHiddenCheck)
324    {
325  0 setHiddenFont(s);
326    }
327  0 drawIdString(gg, hiddenRows, s, i, 0, ypos);
328    }
329   
330  0 if (labels != null)
331    {
332  0 gg.translate(0, ypos + (alheight * avcharHeight));
333  0 labels.drawComponent(gg, getSize().width);
334  0 gg.translate(0, -ypos - (alheight * avcharHeight));
335    }
336  0 ypos += cHeight;
337  0 row += rowSize;
338    }
339    }
340   
 
341  0 toggle public void setHighlighted(List<SequenceI> list)
342    {
343  0 searchResults = list;
344  0 repaint();
345    }
346   
 
347  0 toggle void drawMarker(int i, int starty, int yoffset)
348    {
349  0 SequenceI[] hseqs = av.getAlignment()
350    .getHiddenSequences().hiddenSequences;
351    // Use this method here instead of calling hiddenSeq adjust
352    // 3 times.
353  0 int hSize = hseqs.length;
354   
355  0 int hiddenIndex = i;
356  0 int lastIndex = i - 1;
357  0 int nextIndex = i + 1;
358   
359  0 for (int j = 0; j < hSize; j++)
360    {
361  0 if (hseqs[j] != null)
362    {
363  0 if (j - 1 < hiddenIndex)
364    {
365  0 hiddenIndex++;
366    }
367  0 if (j - 1 < lastIndex)
368    {
369  0 lastIndex++;
370    }
371  0 if (j - 1 < nextIndex)
372    {
373  0 nextIndex++;
374    }
375    }
376    }
377   
378  0 boolean below = (hiddenIndex > lastIndex + 1);
379  0 boolean above = (nextIndex > hiddenIndex + 1);
380   
381  0 gg.setColor(Color.blue);
382  0 if (below)
383    {
384  0 gg.fillPolygon(
385    new int[]
386    { getSize().width - avcharHeight,
387    getSize().width - avcharHeight, getSize().width },
388    new int[]
389    { (i - starty) * avcharHeight + yoffset,
390    (i - starty) * avcharHeight + yoffset + avcharHeight / 4,
391    (i - starty) * avcharHeight + yoffset },
392    3);
393    }
394  0 if (above)
395    {
396  0 gg.fillPolygon(
397    new int[]
398    { getSize().width - avcharHeight,
399    getSize().width - avcharHeight, getSize().width },
400    new int[]
401    { (i - starty + 1) * avcharHeight + yoffset,
402    (i - starty + 1) * avcharHeight + yoffset
403    - avcharHeight / 4,
404    (i - starty + 1) * avcharHeight + yoffset },
405    3);
406   
407    }
408    }
409   
 
410  0 toggle boolean setHiddenFont(SequenceI seq)
411    {
412  0 Font bold = new Font(av.getFont().getName(), Font.BOLD,
413    av.getFont().getSize());
414   
415  0 if (av.isReferenceSeq(seq) || av.isHiddenRepSequence(seq))
416    {
417  0 gg.setFont(bold);
418  0 return true;
419    }
420  0 return false;
421    }
422   
423    /**
424    * Respond to viewport range changes (e.g. alignment panel was scrolled). Both
425    * scrolling and resizing change viewport ranges. Scrolling changes both start
426    * and end points, but resize only changes end values. Here we only want to
427    * fastpaint on a scroll, with resize using a normal paint, so scroll events
428    * are identified as changes to the horizontal or vertical start value.
429    * <p>
430    * In unwrapped mode, only responds to a vertical scroll, as horizontal scroll
431    * leaves sequence ids unchanged. In wrapped mode, only vertical scroll is
432    * provided, but it generates a change of "startres" which does require an
433    * update here.
434    */
 
435  0 toggle @Override
436    public void propertyChange(PropertyChangeEvent evt)
437    {
438  0 String propertyName = evt.getPropertyName();
439  0 if (propertyName.equals(ViewportRanges.STARTSEQ)
440    || (av.getWrapAlignment()
441    && propertyName.equals(ViewportRanges.STARTRES)))
442    {
443  0 fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
444    }
445  0 else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ))
446    {
447  0 fastPaint(((int[]) evt.getNewValue())[1]
448    - ((int[]) evt.getOldValue())[1]);
449    }
450  0 else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT))
451    {
452  0 repaint();
453    }
454    }
455    }