Clover icon

Coverage Report

  1. Project Clover database Wed Dec 3 2025 16:47:11 GMT
  2. Package jalview.gui

File SeqCanvasTest.java

 

Code metrics

2
164
5
1
387
229
7
0.04
32.8
5
1.4

Classes

Class Line # Actions
SeqCanvasTest 43 164 7
0.87719387.7%
 

Contributing tests

This file is covered by 3 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 static org.testng.Assert.assertEquals;
24    import static org.testng.Assert.assertFalse;
25    import static org.testng.Assert.assertNotNull;
26    import static org.testng.Assert.assertNull;
27    import static org.testng.Assert.assertTrue;
28   
29    import java.awt.Font;
30    import java.awt.FontMetrics;
31   
32    import org.testng.annotations.BeforeMethod;
33    import org.testng.annotations.Test;
34   
35    import jalview.bin.Cache;
36    import jalview.datamodel.AlignmentI;
37    import jalview.datamodel.SearchResults;
38    import jalview.datamodel.SearchResultsI;
39    import jalview.io.DataSourceType;
40    import jalview.io.FileLoader;
41    import junit.extensions.PA;
42   
 
43    public class SeqCanvasTest
44    {
45    private AlignFrame af;
46   
47    /**
48    * Test the method that computes wrapped width in residues, height of wrapped
49    * widths in pixels, and the number of widths visible
50    */
 
51  1 toggle @Test(groups = "Functional")
52    public void testCalculateWrappedGeometry_noAnnotations()
53    {
54  1 AlignViewport av = af.getViewport();
55  1 AlignmentI al = av.getAlignment();
56  1 assertEquals(al.getWidth(), 157);
57  1 assertEquals(al.getHeight(), 15);
58  1 av.getRanges().setStartEndSeq(0, 14);
59   
60  1 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
61   
62  1 av.setWrapAlignment(true);
63  1 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
64  1 int charHeight = av.getCharHeight();
65  1 int charWidth = av.getCharWidth();
66  1 assertEquals(charHeight, 17);
67  1 assertEquals(charWidth, 12);
68   
69    /*
70    * first with scales above, left, right
71    */
72  1 av.setShowAnnotation(false);
73  1 av.setScaleAboveWrapped(true);
74  1 av.setScaleLeftWrapped(true);
75  1 av.setScaleRightWrapped(true);
76  1 FontMetrics fm = testee.getFontMetrics(av.getFont());
77  1 int labelWidth = fm.stringWidth("000") + charWidth;
78    // some leeway for different OS rendering of text
79  1 assertTrue(labelWidth >= 36 && labelWidth <= 39);
80   
81    /*
82    * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
83    * take the whole multiple of character widths
84    */
85  1 int canvasWidth = 400;
86  1 int canvasHeight = 300;
87  1 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
88  1 int wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth,
89    canvasHeight);
90  1 int wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
91  1 assertEquals(wrappedWidth, residueColumns);
92  1 assertEquals(wrappedVisibleWidths, 1);
93  1 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
94  1 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
95  1 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
96    2 * charHeight);
97  1 int repeatingHeight = (int) PA.getValue(testee,
98    "wrappedRepeatHeightPx");
99  1 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
100   
101    /*
102    * repeat height is 17 * (2 + 15) = 289
103    * make canvas height 2 * 289 + 3 * charHeight so just enough to
104    * draw 2 widths and the first sequence of a third
105    */
106  1 canvasHeight = charHeight * (17 * 2 + 3);
107  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
108  1 assertEquals(wrappedVisibleWidths, 3);
109   
110    /*
111    * reduce canvas height by 1 pixel
112    * - should not be enough height to draw 3 widths
113    */
114  1 canvasHeight -= 1;
115  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
116  1 assertEquals(wrappedVisibleWidths, 2);
117   
118    /*
119    * turn off scale above - can now fit in 2 and a bit widths
120    */
121  1 av.setScaleAboveWrapped(false);
122  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
123  1 assertEquals(wrappedVisibleWidths, 3);
124   
125    /*
126    * reduce height to enough for 2 widths and not quite a third
127    * i.e. two repeating heights + spacer + sequence - 1 pixel
128    */
129  1 canvasHeight = charHeight * (16 * 2 + 2) - 1;
130  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
131  1 assertEquals(wrappedVisibleWidths, 2);
132   
133    /*
134    * make canvas width enough for scales and 20 residues
135    */
136  1 canvasWidth = 2 * labelWidth + 20 * charWidth;
137  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
138  1 assertEquals(wrappedWidth, 20);
139   
140    /*
141    * reduce width by 1 pixel - rounds down to 19 residues
142    */
143  1 canvasWidth -= 1;
144  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
145  1 assertEquals(wrappedWidth, 19);
146   
147    /*
148    * turn off West scale - adds labelWidth (39) to available for residues
149    * which with the 11 remainder makes 50 which is 4 more charWidths rem 2
150    */
151  1 av.setScaleLeftWrapped(false);
152  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
153    // some leeway for different OS rendering of text
154  1 assertTrue(wrappedWidth >= 22 && wrappedWidth <= 23);
155  1 int difference = wrappedWidth - 23;
156   
157    /*
158    * add 10 pixels to width to fit in another whole residue column
159    */
160  1 canvasWidth += 9;
161  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
162  1 assertEquals(wrappedWidth, 23);
163  1 canvasWidth += 1;
164  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
165  1 assertEquals(wrappedWidth, 24 + difference);
166   
167    /*
168    * turn off East scale to gain 39 more pixels (3 columns remainder 3)
169    */
170  1 av.setScaleRightWrapped(false);
171  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
172  1 assertEquals(wrappedWidth, 27 + difference);
173   
174    /*
175    * add 9 pixels to width to gain a residue column
176    */
177  1 canvasWidth += 8;
178  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
179  1 assertEquals(wrappedWidth, 27); // 8px not enough
180  1 canvasWidth += 1;
181  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
182  1 assertEquals(wrappedWidth, 28 + difference); // 9px is enough
183   
184    /*
185    * now West but not East scale - lose 39 pixels or 4 columns
186    */
187  1 av.setScaleLeftWrapped(true);
188  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
189  1 assertEquals(wrappedWidth, 24);
190   
191    /*
192    * adding 3 pixels to width regains one column
193    */
194  1 canvasWidth += 2;
195  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
196  1 assertEquals(wrappedWidth, 24); // 2px not enough
197  1 canvasWidth += 1;
198  1 wrappedWidth = testee.getWrappedCanvasWidth(canvasWidth);
199  1 assertEquals(wrappedWidth, 25 + difference); // 3px is enough
200   
201    /*
202    * turn off scales left and right, make width exactly 157 columns
203    */
204  1 av.setScaleLeftWrapped(false);
205  1 canvasWidth = al.getWidth() * charWidth;
206  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
207  1 assertEquals(wrappedVisibleWidths, 1);
208    }
209   
210    /**
211    * Test the method that computes wrapped width in residues, height of wrapped
212    * widths in pixels, and the number of widths visible
213    */
 
214  1 toggle @Test(groups = "Functional")
215    public void testCalculateWrappedGeometry_withAnnotations()
216    {
217  1 AlignViewport av = af.getViewport();
218  1 AlignmentI al = av.getAlignment();
219  1 assertEquals(al.getWidth(), 157);
220  1 assertEquals(al.getHeight(), 15);
221   
222  1 av.setWrapAlignment(true);
223  1 av.getRanges().setStartEndSeq(0, 14);
224  1 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
225  1 int charHeight = av.getCharHeight();
226  1 int charWidth = av.getCharWidth();
227  1 assertEquals(charHeight, 17);
228  1 assertEquals(charWidth, 12);
229   
230  1 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
231   
232    /*
233    * first with scales above, left, right
234    */
235  1 av.setShowAnnotation(true);
236  1 av.setScaleAboveWrapped(true);
237  1 av.setScaleLeftWrapped(true);
238  1 av.setScaleRightWrapped(true);
239  1 FontMetrics fm = testee.getFontMetrics(av.getFont());
240  1 int labelWidth = fm.stringWidth("000") + charWidth;
241    // some leeway for different OS rendering of text
242  1 assertTrue(labelWidth >= 36 && labelWidth <= 39);
243  1 int annotationHeight = testee.getAnnotationHeight();
244   
245    /*
246    * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
247    * take the whole multiple of character widths
248    */
249  1 int canvasWidth = 400;
250  1 int canvasHeight = 300;
251  1 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
252  1 int wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth,
253    canvasHeight);
254  1 int wrappedWidth = testee.av.getWrappedWidth();
255  1 assertEquals(wrappedWidth, residueColumns);
256  1 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
257  1 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
258  1 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
259    2 * charHeight);
260  1 int repeatingHeight = (int) PA.getValue(testee,
261    "wrappedRepeatHeightPx");
262  1 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
263    + SeqCanvas.SEQS_ANNOTATION_GAP + annotationHeight);
264  1 assertEquals(wrappedVisibleWidths, 1);
265   
266    /*
267    * repeat height is 17 * (2 + 15) = 289 + 3 + annotationHeight = 510
268    * make canvas height 2 of these plus 3 charHeights
269    * so just enough to draw 2 widths, gap + scale + the first sequence of a third
270    */
271  1 canvasHeight = charHeight * (17 * 2 + 3)
272    + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP);
273  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
274  1 assertEquals(wrappedVisibleWidths, 3);
275   
276    /*
277    * reduce canvas height by 1 pixel - should not be enough height
278    * to draw 3 widths
279    */
280  1 canvasHeight -= 1;
281  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
282  1 assertEquals(wrappedVisibleWidths, 2);
283   
284    /*
285    * turn off scale above - can now fit in 2 and a bit widths
286    */
287  1 av.setScaleAboveWrapped(false);
288  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
289  1 assertEquals(wrappedVisibleWidths, 3);
290   
291    /*
292    * reduce height to enough for 2 widths and not quite a third
293    * i.e. two repeating heights + spacer + sequence - 1 pixel
294    */
295  1 canvasHeight = charHeight * (16 * 2 + 2)
296    + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP) - 1;
297  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
298  1 assertEquals(wrappedVisibleWidths, 2);
299   
300    /*
301    * add 1 pixel to height - should now get 3 widths drawn
302    */
303  1 canvasHeight += 1;
304  1 wrappedVisibleWidths = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
305  1 assertEquals(wrappedVisibleWidths, 3);
306    }
307   
308    /**
309    * Test simulates loading an unwrapped alignment, shrinking it vertically so
310    * not all sequences are visible, then changing to wrapped mode. The ranges
311    * endSeq should be unchanged, but the vertical repeat height should include
312    * all sequences.
313    */
 
314  0 toggle @Test(groups = "Functional_Failing")
315    public void testCalculateWrappedGeometry_fromScrolled()
316    {
317  0 AlignViewport av = af.getViewport();
318  0 AlignmentI al = av.getAlignment();
319  0 assertEquals(al.getWidth(), 157);
320  0 assertEquals(al.getHeight(), 15);
321  0 av.getRanges().setStartEndSeq(0, 3);
322  0 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
323  0 av.setWrapAlignment(true);
324  0 av.setShowAnnotation(false);
325  0 av.setScaleAboveWrapped(true);
326   
327  0 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
328   
329  0 int charHeight = av.getCharHeight();
330  0 int charWidth = av.getCharWidth();
331  0 assertEquals(charHeight, 17);
332  0 assertEquals(charWidth, 12);
333   
334  0 int canvasWidth = 400;
335  0 int canvasHeight = 300;
336  0 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
337   
338  0 assertEquals(av.getRanges().getEndSeq(), 3); // unchanged
339  0 int repeatingHeight = (int) PA.getValue(testee,
340    "wrappedRepeatHeightPx");
341  0 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
342    }
343   
 
344  3 toggle @BeforeMethod(alwaysRun = true)
345    public void setUp()
346    {
347  3 Cache.loadProperties("test/jalview/io/testProps.jvprops");
348  3 Cache.applicationProperties.setProperty("SHOW_IDENTITY",
349    Boolean.TRUE.toString());
350  3 af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
351    DataSourceType.FILE);
352   
353    /*
354    * wait for Consensus thread to complete
355    */
356  3 do
357    {
358  6 try
359    {
360  6 Thread.sleep(50);
361    } catch (InterruptedException x)
362    {
363    }
364  6 } while (af.getViewport().getCalcManager().isWorking());
365    }
366   
 
367  1 toggle @Test(groups = "Functional")
368    public void testClear_HighlightAndSelection()
369    {
370  1 AlignViewport av = af.getViewport();
371  1 SearchResultsI highlight = new SearchResults();
372  1 highlight.addResult(
373    av.getAlignment().getSequenceAt(1).getDatasetSequence(), 50,
374    80);
375  1 af.alignPanel.highlightSearchResults(highlight);
376  1 af.avc.markHighlightedColumns(false, false, false);
377  1 assertNotNull(av.getSearchResults(),
378    "No highlight was created on alignment");
379  1 assertFalse(av.getColumnSelection().isEmpty(),
380    "No selection was created from highlight");
381  1 af.deselectAllSequenceMenuItem_actionPerformed(null);
382  1 assertTrue(av.getColumnSelection().isEmpty(),
383    "No Selection should be present after deselecting all.");
384  1 assertNull(av.getSearchResults(),
385    "No higlighted search results should be present after deselecting all.");
386    }
387    }