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;
41 import jalview.util.Platform;
42 import jalview.viewmodel.ViewportRanges;
43 import junit.extensions.PA;
45 public class SeqCanvasTest
47 @BeforeClass(alwaysRun = true)
50 Cache.loadProperties(null);
52 Desktop.getInstance().setVisible(false);
56 * Test the method that computes wrapped width in residues, height of wrapped
57 * widths in pixels, and the number of widths visible
59 @Test(groups = "Functional")
60 public void testCalculateWrappedGeometry_noAnnotations()
62 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
63 "examples/uniref50.fa", DataSourceType.FILE);
65 AlignViewport av = af.getViewport();
66 AlignmentI al = av.getAlignment();
67 assertEquals(al.getWidth(), 157);
68 assertEquals(al.getHeight(), 15);
69 av.getRanges().setStartEndSeq(0, 14);
71 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
73 av.setWrapAlignment(true);
74 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
75 int charHeight = av.getCharHeight();
76 int charWidth = av.getCharWidth();
77 assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
78 assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
81 * first with scales above, left, right
83 av.setShowAnnotation(false);
84 av.setScaleAboveWrapped(true);
85 av.setScaleLeftWrapped(true);
86 av.setScaleRightWrapped(true);
87 FontMetrics fm = testee.getFontMetrics(av.getFont());
88 int labelWidth = fm.stringWidth("000") + charWidth;
89 assertEquals(labelWidth,
90 !Platform.isWin() ? 3 * 9 + charWidth : 3 * 8 + charWidth);
93 * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
94 * take the whole multiple of character widths
96 int canvasWidth = 400;
97 int canvasHeight = 300;
98 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
99 int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
100 assertEquals(wrappedWidth, residueColumns);
101 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
102 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
103 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
105 int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
106 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
107 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
110 * repeat height is 17 * (2 + 15) = 289
111 * make canvas height 2 * 289 + 3 * charHeight so just enough to
112 * draw 2 widths and the first sequence of a third
114 canvasHeight = charHeight * (17 * 2 + 3);
115 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
116 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
119 * reduce canvas height by 1 pixel
120 * - should not be enough height to draw 3 widths
123 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
124 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
127 * turn off scale above - can now fit in 2 and a bit widths
129 av.setScaleAboveWrapped(false);
130 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
131 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
134 * reduce height to enough for 2 widths and not quite a third
135 * i.e. two repeating heights + spacer + sequence - 1 pixel
137 canvasHeight = charHeight * (16 * 2 + 2) - 1;
138 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
139 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
142 * make canvas width enough for scales and 20 residues
144 canvasWidth = 2 * labelWidth + 20 * charWidth;
145 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
147 assertEquals(wrappedWidth, 20);
150 * reduce width by 1 pixel - rounds down to 19 residues
153 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
155 assertEquals(wrappedWidth, 19);
158 * turn off West scale - adds labelWidth (39) to available for residues
159 * which with the 11 remainder makes 50 which is 4 more charWidths rem 2
161 av.setScaleLeftWrapped(false);
162 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
164 assertEquals(wrappedWidth, 23);
167 * add 10 pixels to width to fit in another whole residue column
170 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
172 assertEquals(wrappedWidth, 23);
174 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
176 assertEquals(wrappedWidth, 24);
179 * turn off East scale to gain 39 more pixels (3 columns remainder 3)
181 av.setScaleRightWrapped(false);
182 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
184 assertEquals(wrappedWidth, 27);
187 * add 9 pixels to width to gain a residue column
190 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
192 assertEquals(wrappedWidth, 27); // 8px not enough
194 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
196 assertEquals(wrappedWidth, 28); // 9px is enough
199 * now West but not East scale - lose 39 pixels or 4 columns
201 av.setScaleLeftWrapped(true);
202 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
204 assertEquals(wrappedWidth, 24);
207 * adding 3 pixels to width regains one column
210 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
212 assertEquals(wrappedWidth, !Platform.isWin() ? 24 : 25); // 2px not enough
214 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
216 assertEquals(wrappedWidth, 25); // 3px is enough
219 * turn off scales left and right, make width exactly 157 columns
221 av.setScaleLeftWrapped(false);
222 canvasWidth = al.getWidth() * charWidth;
223 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
224 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
228 * Test the method that computes wrapped width in residues, height of wrapped
229 * widths in pixels, and the number of widths visible
231 @Test(groups = "Functional")
232 public void testCalculateWrappedGeometry_withAnnotations()
234 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
235 "examples/uniref50.fa", DataSourceType.FILE);
236 AlignViewport av = af.getViewport();
237 AlignmentI al = av.getAlignment();
238 assertEquals(al.getWidth(), 157);
239 assertEquals(al.getHeight(), 15);
241 av.setWrapAlignment(true);
242 av.getRanges().setStartEndSeq(0, 14);
243 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
244 int charHeight = av.getCharHeight();
245 int charWidth = av.getCharWidth();
247 assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
248 assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
250 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
253 * first with scales above, left, right
255 av.setShowAnnotation(true);
256 av.setScaleAboveWrapped(true);
257 av.setScaleLeftWrapped(true);
258 av.setScaleRightWrapped(true);
260 FontMetrics fm = testee.getFontMetrics(av.getFont());
261 int labelWidth = fm.stringWidth("000") + charWidth;
262 assertEquals(labelWidth,
263 !Platform.isWin() ? 3 * 9 + charWidth : 3 * 8 + charWidth);
265 int annotationHeight = testee.getAnnotationHeight();
268 * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
269 * take the whole multiple of character widths
271 int canvasWidth = 400;
272 int canvasHeight = 300;
273 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
274 int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
275 assertEquals(wrappedWidth, residueColumns);
276 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
277 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
278 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
280 int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
281 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
282 + SeqCanvas.SEQS_ANNOTATION_GAP + annotationHeight);
283 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
286 * repeat height is 17 * (2 + 15) = 289 + 3 + annotationHeight = 510
287 * make canvas height 2 of these plus 3 charHeights
288 * so just enough to draw 2 widths, gap + scale + the first sequence of a third
290 canvasHeight = charHeight * (17 * 2 + 3)
291 + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP);
292 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
293 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
296 * reduce canvas height by 1 pixel - should not be enough height
300 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
301 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
304 * turn off scale above - can now fit in 2 and a bit widths
306 av.setScaleAboveWrapped(false);
307 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
308 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
311 * reduce height to enough for 2 widths and not quite a third
312 * i.e. two repeating heights + spacer + sequence - 1 pixel
314 canvasHeight = charHeight * (16 * 2 + 2)
315 + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP) - 1;
316 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
317 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
320 * add 1 pixel to height - should now get 3 widths drawn
323 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
324 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
328 * Test simulates loading an unwrapped alignment, shrinking it vertically so
329 * not all sequences are visible, then changing to wrapped mode. The ranges
330 * endSeq should be unchanged, but the vertical repeat height should include
333 @Test(groups = "Functional")
334 public void testCalculateWrappedGeometry_fromScrolled()
336 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
337 "examples/uniref50.fa", DataSourceType.FILE);
339 System.out.println("ap dim = " + af.alignPanel.getSize());
340 System.out.println("seqpan dim = " + af.alignPanel.getSeqPanel().getSize());
341 System.out.println("seqcan dim = " + af.alignPanel.getSeqPanel().seqCanvas.getSize());
344 AlignViewport av = af.getViewport();
345 AlignmentI al = av.getAlignment();
346 assertEquals(al.getWidth(), 157);
347 assertEquals(al.getHeight(), 15);
349 ViewportRanges ranges = av.getRanges();
350 System.out.println(ranges + " before setting to 3");
351 ranges.setStartEndSeq(0, 3);
352 int endSeq = ranges.getEndSeq();
353 System.out.println(ranges + " after setting to 3");
354 av.setShowAnnotation(false);
355 av.setScaleAboveWrapped(true);
357 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
358 av.setWrapAlignment(true);
359 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
360 int charHeight = av.getCharHeight();
361 int charWidth = av.getCharWidth();
362 // Windows h=19, w=11.
363 assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
364 assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
366 int canvasWidth = 400;
367 int canvasHeight = 300;
368 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
369 System.out.println(ranges);
370 assertEquals(ranges.getEndSeq(), endSeq); // unchanged
371 int repeatingHeight = (int) PA.getValue(testee,
372 "wrappedRepeatHeightPx");
373 int h = charHeight * (2 + al.getHeight());
374 assertEquals(repeatingHeight, h);
376 @Test(groups = "Functional")
377 public void testClear_HighlightAndSelection()
379 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
380 "examples/uniref50.fa", DataSourceType.FILE);
381 AlignViewport av = af.getViewport();
382 SearchResultsI highlight = new SearchResults();
384 av.getAlignment().getSequenceAt(1).getDatasetSequence(), 50,
386 af.alignPanel.highlightSearchResults(highlight);
387 af.avc.markHighlightedColumns(false, false, false);
388 assertNotNull(av.getSearchResults(),
389 "No highlight was created on alignment");
390 assertFalse(av.getColumnSelection().isEmpty(),
391 "No selection was created from highlight");
392 af.deselectAllSequenceMenuItem_actionPerformed(null);
393 assertTrue(av.getColumnSelection().isEmpty(),
394 "No Selection should be present after deselecting all.");
395 assertNull(av.getSearchResults(),
396 "No higlighted search results should be present after deselecting all.");