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.
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;
30 import java.awt.FontMetrics;
32 import org.testng.annotations.BeforeClass;
33 import org.testng.annotations.Test;
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;
42 import jalview.util.Platform;
43 import jalview.viewmodel.ViewportRanges;
44 import junit.extensions.PA;
46 public class SeqCanvasTest
48 @BeforeClass(alwaysRun = true)
51 // 2.11.2 - beforeMethod setup
52 // Cache.loadProperties("test/jalview/io/testProps.jvprops");
53 //Cache.applicationProperties.setProperty("SHOW_IDENTITY",
54 // Boolean.TRUE.toString());
55 // af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
56 // DataSourceType.FILE);
58 // * wait for Consensus thread to complete
65 //} catch (InterruptedException x)
68 // } while (af.getViewport().getCalcManager().isWorking());
70 Cache.loadProperties(null);
71 Desktop.getInstance().setVisible(false);
74 private AlignFrame af;
77 * Test the method that computes wrapped width in residues, height of wrapped
78 * widths in pixels, and the number of widths visible
80 @Test(groups = "Functional")
81 public void testCalculateWrappedGeometry_noAnnotations()
83 AlignViewport av = af.getViewport();
84 AlignmentI al = av.getAlignment();
85 assertEquals(al.getWidth(), 157);
86 assertEquals(al.getHeight(), 15);
87 av.getRanges().setStartEndSeq(0, 14);
89 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
91 av.setWrapAlignment(true);
92 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
93 int charHeight = av.getCharHeight();
94 int charWidth = av.getCharWidth();
95 assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
96 assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
99 * first with scales above, left, right
101 av.setShowAnnotation(false);
102 av.setScaleAboveWrapped(true);
103 av.setScaleLeftWrapped(true);
104 av.setScaleRightWrapped(true);
105 FontMetrics fm = testee.getFontMetrics(av.getFont());
106 int labelWidth = fm.stringWidth("000") + charWidth;
107 assertEquals(labelWidth,
108 !Platform.isWin() ? 3 * 9 + charWidth : 3 * 8 + charWidth);
111 * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
112 * take the whole multiple of character widths
114 int canvasWidth = 400;
115 int canvasHeight = 300;
116 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
117 int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
118 assertEquals(wrappedWidth, residueColumns);
119 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
120 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
121 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
123 int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
124 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
125 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
128 * repeat height is 17 * (2 + 15) = 289
129 * make canvas height 2 * 289 + 3 * charHeight so just enough to
130 * draw 2 widths and the first sequence of a third
132 canvasHeight = charHeight * (17 * 2 + 3);
133 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
134 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
137 * reduce canvas height by 1 pixel
138 * - should not be enough height to draw 3 widths
141 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
142 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
145 * turn off scale above - can now fit in 2 and a bit widths
147 av.setScaleAboveWrapped(false);
148 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
149 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
152 * reduce height to enough for 2 widths and not quite a third
153 * i.e. two repeating heights + spacer + sequence - 1 pixel
155 canvasHeight = charHeight * (16 * 2 + 2) - 1;
156 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
157 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
160 * make canvas width enough for scales and 20 residues
162 canvasWidth = 2 * labelWidth + 20 * charWidth;
163 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
165 assertEquals(wrappedWidth, 20);
168 * reduce width by 1 pixel - rounds down to 19 residues
171 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
173 assertEquals(wrappedWidth, 19);
176 * turn off West scale - adds labelWidth (39) to available for residues
177 * which with the 11 remainder makes 50 which is 4 more charWidths rem 2
179 av.setScaleLeftWrapped(false);
180 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
182 assertEquals(wrappedWidth, 23);
185 * add 10 pixels to width to fit in another whole residue column
188 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
190 assertEquals(wrappedWidth, 23);
192 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
194 assertEquals(wrappedWidth, 24);
197 * turn off East scale to gain 39 more pixels (3 columns remainder 3)
199 av.setScaleRightWrapped(false);
200 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
202 assertEquals(wrappedWidth, 27);
205 * add 9 pixels to width to gain a residue column
208 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
210 assertEquals(wrappedWidth, 27); // 8px not enough
212 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
214 assertEquals(wrappedWidth, 28); // 9px is enough
217 * now West but not East scale - lose 39 pixels or 4 columns
219 av.setScaleLeftWrapped(true);
220 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
222 assertEquals(wrappedWidth, 24);
225 * adding 3 pixels to width regains one column
228 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
230 assertEquals(wrappedWidth, !Platform.isWin() ? 24 : 25); // 2px not enough
232 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
234 assertEquals(wrappedWidth, 25); // 3px is enough
237 * turn off scales left and right, make width exactly 157 columns
239 av.setScaleLeftWrapped(false);
240 canvasWidth = al.getWidth() * charWidth;
241 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
242 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
246 * Test the method that computes wrapped width in residues, height of wrapped
247 * widths in pixels, and the number of widths visible
249 @Test(groups = "Functional")
250 public void testCalculateWrappedGeometry_withAnnotations()
252 AlignViewport av = af.getViewport();
253 AlignmentI al = av.getAlignment();
254 assertEquals(al.getWidth(), 157);
255 assertEquals(al.getHeight(), 15);
257 av.setWrapAlignment(true);
258 av.getRanges().setStartEndSeq(0, 14);
259 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
260 int charHeight = av.getCharHeight();
261 int charWidth = av.getCharWidth();
262 assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
263 assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
264 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
267 * first with scales above, left, right
269 av.setShowAnnotation(true);
270 av.setScaleAboveWrapped(true);
271 av.setScaleLeftWrapped(true);
272 av.setScaleRightWrapped(true);
273 FontMetrics fm = testee.getFontMetrics(av.getFont());
274 int labelWidth = fm.stringWidth("000") + charWidth;
275 assertEquals(labelWidth,
276 !Platform.isWin() ? 3 * 9 + charWidth : 3 * 8 + charWidth);
277 int annotationHeight = testee.getAnnotationHeight();
280 * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
281 * take the whole multiple of character widths
283 int canvasWidth = 400;
284 int canvasHeight = 300;
285 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
286 int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
287 assertEquals(wrappedWidth, residueColumns);
288 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
289 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
290 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
292 int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
293 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
294 + SeqCanvas.SEQS_ANNOTATION_GAP + annotationHeight);
295 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
298 * repeat height is 17 * (2 + 15) = 289 + 3 + annotationHeight = 510
299 * make canvas height 2 of these plus 3 charHeights
300 * so just enough to draw 2 widths, gap + scale + the first sequence of a third
302 canvasHeight = charHeight * (17 * 2 + 3)
303 + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP);
304 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
305 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
308 * reduce canvas height by 1 pixel - should not be enough height
312 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
313 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
316 * turn off scale above - can now fit in 2 and a bit widths
318 av.setScaleAboveWrapped(false);
319 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
320 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
323 * reduce height to enough for 2 widths and not quite a third
324 * i.e. two repeating heights + spacer + sequence - 1 pixel
326 canvasHeight = charHeight * (16 * 2 + 2)
327 + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP) - 1;
328 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
329 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
332 * add 1 pixel to height - should now get 3 widths drawn
335 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
336 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
340 * Test simulates loading an unwrapped alignment, shrinking it vertically so
341 * not all sequences are visible, then changing to wrapped mode. The ranges
342 * endSeq should be unchanged, but the vertical repeat height should include
345 @Test(groups = "Functional_Failing")
346 public void testCalculateWrappedGeometry_fromScrolled()
348 AlignViewport av = af.getViewport();
349 AlignmentI al = av.getAlignment();
350 assertEquals(al.getWidth(), 157);
351 assertEquals(al.getHeight(), 15);
352 av.getRanges().setStartEndSeq(0, 3);
353 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
354 av.setWrapAlignment(true);
355 av.setShowAnnotation(false);
356 av.setScaleAboveWrapped(true);
358 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
360 int charHeight = av.getCharHeight();
361 int charWidth = av.getCharWidth();
362 assertEquals(charHeight, 17);
363 assertEquals(charWidth, 12);
365 int canvasWidth = 400;
366 int canvasHeight = 300;
367 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
369 assertEquals(av.getRanges().getEndSeq(), 3); // unchanged
370 int repeatingHeight = (int) PA.getValue(testee,
371 "wrappedRepeatHeightPx");
372 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
375 @Test(groups = "Functional")
376 public void testClear_HighlightAndSelection()
378 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
379 "examples/uniref50.fa", DataSourceType.FILE);
380 AlignViewport av = af.getViewport();
381 SearchResultsI highlight = new SearchResults();
383 av.getAlignment().getSequenceAt(1).getDatasetSequence(), 50,
385 af.alignPanel.highlightSearchResults(highlight);
386 af.avc.markHighlightedColumns(false, false, false);
387 assertNotNull(av.getSearchResults(),
388 "No highlight was created on alignment");
389 assertFalse(av.getColumnSelection().isEmpty(),
390 "No selection was created from highlight");
391 af.deselectAllSequenceMenuItem_actionPerformed(null);
392 assertTrue(av.getColumnSelection().isEmpty(),
393 "No Selection should be present after deselecting all.");
394 assertNull(av.getSearchResults(),
395 "No higlighted search results should be present after deselecting all.");