2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
24 import java.awt.FontMetrics;
26 import org.testng.annotations.BeforeMethod;
27 import org.testng.annotations.Test;
28 import static org.testng.Assert.assertEquals;
29 import static org.testng.Assert.assertFalse;
30 import static org.testng.Assert.assertNotNull;
31 import static org.testng.Assert.assertNull;
32 import static org.testng.Assert.assertTrue;
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.DataSourceType;
41 import jalview.io.FileLoader;
43 import junit.extensions.PA;
45 public class SeqCanvasTest
47 private AlignFrame af;
50 * Test the method that computes wrapped width in residues, height of wrapped
51 * widths in pixels, and the number of widths visible
53 @Test(groups = "Functional")
54 public void testCalculateWrappedGeometry_noAnnotations()
56 AlignViewport av = af.getViewport();
57 AlignmentI al = av.getAlignment();
58 assertEquals(al.getWidth(), 157);
59 assertEquals(al.getHeight(), 15);
60 av.getRanges().setStartEndSeq(0, 14);
62 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
64 av.setWrapAlignment(true);
65 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
66 int charHeight = av.getCharHeight();
67 int charWidth = av.getCharWidth();
68 assertEquals(charHeight, 17);
69 assertEquals(charWidth, 12);
72 * first with scales above, left, right
74 av.setShowAnnotation(false);
75 av.setScaleAboveWrapped(true);
76 av.setScaleLeftWrapped(true);
77 av.setScaleRightWrapped(true);
78 FontMetrics fm = testee.getFontMetrics(av.getFont());
79 int labelWidth = fm.stringWidth("000") + charWidth;
80 assertEquals(labelWidth, 39); // 3 x 9 + charWidth
83 * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
84 * take the whole multiple of character widths
86 int canvasWidth = 400;
87 int canvasHeight = 300;
88 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
89 int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
90 assertEquals(wrappedWidth, residueColumns);
91 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
92 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
93 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
95 int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
96 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
97 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
100 * repeat height is 17 * (2 + 15) = 289
101 * make canvas height 2 * 289 + 3 * charHeight so just enough to
102 * draw 2 widths and the first sequence of a third
104 canvasHeight = charHeight * (17 * 2 + 3);
105 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
106 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
109 * reduce canvas height by 1 pixel
110 * - should not be enough height to draw 3 widths
113 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
114 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
117 * turn off scale above - can now fit in 2 and a bit widths
119 av.setScaleAboveWrapped(false);
120 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
121 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
124 * reduce height to enough for 2 widths and not quite a third
125 * i.e. two repeating heights + spacer + sequence - 1 pixel
127 canvasHeight = charHeight * (16 * 2 + 2) - 1;
128 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
129 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
132 * make canvas width enough for scales and 20 residues
134 canvasWidth = 2 * labelWidth + 20 * charWidth;
135 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
137 assertEquals(wrappedWidth, 20);
140 * reduce width by 1 pixel - rounds down to 19 residues
143 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
145 assertEquals(wrappedWidth, 19);
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
151 av.setScaleLeftWrapped(false);
152 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
154 assertEquals(wrappedWidth, 23);
157 * add 10 pixels to width to fit in another whole residue column
160 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
162 assertEquals(wrappedWidth, 23);
164 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
166 assertEquals(wrappedWidth, 24);
169 * turn off East scale to gain 39 more pixels (3 columns remainder 3)
171 av.setScaleRightWrapped(false);
172 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
174 assertEquals(wrappedWidth, 27);
177 * add 9 pixels to width to gain a residue column
180 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
182 assertEquals(wrappedWidth, 27); // 8px not enough
184 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
186 assertEquals(wrappedWidth, 28); // 9px is enough
189 * now West but not East scale - lose 39 pixels or 4 columns
191 av.setScaleLeftWrapped(true);
192 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
194 assertEquals(wrappedWidth, 24);
197 * adding 3 pixels to width regains one column
200 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
202 assertEquals(wrappedWidth, 24); // 2px not enough
204 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
206 assertEquals(wrappedWidth, 25); // 3px is enough
209 * turn off scales left and right, make width exactly 157 columns
211 av.setScaleLeftWrapped(false);
212 canvasWidth = al.getWidth() * charWidth;
213 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
214 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
218 * Test the method that computes wrapped width in residues, height of wrapped
219 * widths in pixels, and the number of widths visible
221 @Test(groups = "Functional")
222 public void testCalculateWrappedGeometry_withAnnotations()
224 AlignViewport av = af.getViewport();
225 AlignmentI al = av.getAlignment();
226 assertEquals(al.getWidth(), 157);
227 assertEquals(al.getHeight(), 15);
229 av.setWrapAlignment(true);
230 av.getRanges().setStartEndSeq(0, 14);
231 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
232 int charHeight = av.getCharHeight();
233 int charWidth = av.getCharWidth();
234 assertEquals(charHeight, 17);
235 assertEquals(charWidth, 12);
237 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
240 * first with scales above, left, right
242 av.setShowAnnotation(true);
243 av.setScaleAboveWrapped(true);
244 av.setScaleLeftWrapped(true);
245 av.setScaleRightWrapped(true);
246 FontMetrics fm = testee.getFontMetrics(av.getFont());
247 int labelWidth = fm.stringWidth("000") + charWidth;
248 assertEquals(labelWidth, 39); // 3 x 9 + charWidth
249 int annotationHeight = testee.getAnnotationHeight();
252 * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
253 * take the whole multiple of character widths
255 int canvasWidth = 400;
256 int canvasHeight = 300;
257 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
258 int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
259 assertEquals(wrappedWidth, residueColumns);
260 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
261 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
262 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
264 int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
265 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
266 + SeqCanvas.SEQS_ANNOTATION_GAP + annotationHeight);
267 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
270 * repeat height is 17 * (2 + 15) = 289 + 3 + annotationHeight = 510
271 * make canvas height 2 of these plus 3 charHeights
272 * so just enough to draw 2 widths, gap + scale + the first sequence of a third
274 canvasHeight = charHeight * (17 * 2 + 3)
275 + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP);
276 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
277 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
280 * reduce canvas height by 1 pixel - should not be enough height
284 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
285 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
288 * turn off scale above - can now fit in 2 and a bit widths
290 av.setScaleAboveWrapped(false);
291 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
292 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
295 * reduce height to enough for 2 widths and not quite a third
296 * i.e. two repeating heights + spacer + sequence - 1 pixel
298 canvasHeight = charHeight * (16 * 2 + 2)
299 + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP) - 1;
300 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
301 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
304 * add 1 pixel to height - should now get 3 widths drawn
307 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
308 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
312 * Test simulates loading an unwrapped alignment, shrinking it vertically so
313 * not all sequences are visible, then changing to wrapped mode. The ranges
314 * endSeq should be unchanged, but the vertical repeat height should include
317 @Test(groups = "Functional_Failing")
318 public void testCalculateWrappedGeometry_fromScrolled()
320 AlignViewport av = af.getViewport();
321 AlignmentI al = av.getAlignment();
322 assertEquals(al.getWidth(), 157);
323 assertEquals(al.getHeight(), 15);
324 av.getRanges().setStartEndSeq(0, 3);
325 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
326 av.setWrapAlignment(true);
327 av.setShowAnnotation(false);
328 av.setScaleAboveWrapped(true);
330 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
332 int charHeight = av.getCharHeight();
333 int charWidth = av.getCharWidth();
334 assertEquals(charHeight, 17);
335 assertEquals(charWidth, 12);
337 int canvasWidth = 400;
338 int canvasHeight = 300;
339 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
341 assertEquals(av.getRanges().getEndSeq(), 3); // unchanged
342 int repeatingHeight = (int) PA.getValue(testee,
343 "wrappedRepeatHeightPx");
344 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
347 @BeforeMethod(alwaysRun = true)
350 Cache.loadProperties("test/jalview/io/testProps.jvprops");
351 Cache.applicationProperties.setProperty("SHOW_IDENTITY",
352 Boolean.TRUE.toString());
353 af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
354 DataSourceType.FILE);
357 * wait for Consensus thread to complete
364 } catch (InterruptedException x)
367 } while (af.getViewport().getCalcManager().isWorking());
369 @Test(groups = "Functional")
370 public void testClear_HighlightAndSelection()
372 AlignViewport av = af.getViewport();
373 SearchResultsI highlight = new SearchResults();
375 av.getAlignment().getSequenceAt(1).getDatasetSequence(), 50,
377 af.alignPanel.highlightSearchResults(highlight);
378 af.avc.markHighlightedColumns(false, false, false);
379 assertNotNull(av.getSearchResults(),
380 "No highlight was created on alignment");
381 assertFalse(av.getColumnSelection().isEmpty(),
382 "No selection was created from highlight");
383 af.deselectAllSequenceMenuItem_actionPerformed(null);
384 assertTrue(av.getColumnSelection().isEmpty(),
385 "No Selection should be present after deselecting all.");
386 assertNull(av.getSearchResults(),
387 "No higlighted search results should be present after deselecting all.");