Clover icon

Coverage Report

  1. Project Clover database Tue Mar 10 2026 14:58:44 GMT
  2. Package jalview.gui

File SeqCanvasTest.java

 

Code metrics

16
168
6
1
398
239
15
0.09
28
6
2.5

Classes

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