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 jalview.bin.Cache;
24 import jalview.bin.Jalview;
25 import jalview.datamodel.AlignmentI;
26 import jalview.io.DataSourceType;
27 import jalview.datamodel.SearchResults;
28 import jalview.datamodel.SearchResultsI;
29 import jalview.io.FileLoader;
30 import jalview.util.Platform;
31 import jalview.viewmodel.ViewportRanges;
34 import java.awt.FontMetrics;
36 import org.testng.annotations.BeforeClass;
37 import org.testng.annotations.Test;
38 import static org.testng.Assert.assertEquals;
39 import static org.testng.Assert.assertFalse;
40 import static org.testng.Assert.assertNotNull;
41 import static org.testng.Assert.assertNull;
42 import static org.testng.Assert.assertTrue;
44 import junit.extensions.PA;
46 public class SeqCanvasTest
48 @BeforeClass(alwaysRun = true)
51 Cache.loadProperties(null);
53 Desktop.getInstance().setVisible(false);
57 * Test the method that computes wrapped width in residues, height of wrapped
58 * widths in pixels, and the number of widths visible
60 @Test(groups = "Functional")
61 public void testCalculateWrappedGeometry_noAnnotations()
63 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
64 "examples/uniref50.fa", DataSourceType.FILE);
66 AlignViewport av = af.getViewport();
67 AlignmentI al = av.getAlignment();
68 assertEquals(al.getWidth(), 157);
69 assertEquals(al.getHeight(), 15);
70 av.getRanges().setStartEndSeq(0, 14);
72 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
74 av.setWrapAlignment(true);
75 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
76 int charHeight = av.getCharHeight();
77 int charWidth = av.getCharWidth();
78 assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
79 assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
82 * first with scales above, left, right
84 av.setShowAnnotation(false);
85 av.setScaleAboveWrapped(true);
86 av.setScaleLeftWrapped(true);
87 av.setScaleRightWrapped(true);
88 FontMetrics fm = testee.getFontMetrics(av.getFont());
89 int labelWidth = fm.stringWidth("000") + charWidth;
90 assertEquals(labelWidth,
91 !Platform.isWin() ? 3 * 9 + charWidth : 3 * 8 + charWidth);
94 * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
95 * take the whole multiple of character widths
97 int canvasWidth = 400;
98 int canvasHeight = 300;
99 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
100 int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
101 assertEquals(wrappedWidth, residueColumns);
102 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
103 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
104 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
106 int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
107 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
108 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
111 * repeat height is 17 * (2 + 15) = 289
112 * make canvas height 2 * 289 + 3 * charHeight so just enough to
113 * draw 2 widths and the first sequence of a third
115 canvasHeight = charHeight * (17 * 2 + 3);
116 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
117 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
120 * reduce canvas height by 1 pixel
121 * - should not be enough height to draw 3 widths
124 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
125 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
128 * turn off scale above - can now fit in 2 and a bit widths
130 av.setScaleAboveWrapped(false);
131 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
132 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
135 * reduce height to enough for 2 widths and not quite a third
136 * i.e. two repeating heights + spacer + sequence - 1 pixel
138 canvasHeight = charHeight * (16 * 2 + 2) - 1;
139 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
140 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
143 * make canvas width enough for scales and 20 residues
145 canvasWidth = 2 * labelWidth + 20 * charWidth;
146 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
148 assertEquals(wrappedWidth, 20);
151 * reduce width by 1 pixel - rounds down to 19 residues
154 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
156 assertEquals(wrappedWidth, 19);
159 * turn off West scale - adds labelWidth (39) to available for residues
160 * which with the 11 remainder makes 50 which is 4 more charWidths rem 2
162 av.setScaleLeftWrapped(false);
163 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
165 assertEquals(wrappedWidth, 23);
168 * add 10 pixels to width to fit in another whole residue column
171 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
173 assertEquals(wrappedWidth, 23);
175 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
177 assertEquals(wrappedWidth, 24);
180 * turn off East scale to gain 39 more pixels (3 columns remainder 3)
182 av.setScaleRightWrapped(false);
183 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
185 assertEquals(wrappedWidth, 27);
188 * add 9 pixels to width to gain a residue column
191 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
193 assertEquals(wrappedWidth, 27); // 8px not enough
195 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
197 assertEquals(wrappedWidth, 28); // 9px is enough
200 * now West but not East scale - lose 39 pixels or 4 columns
202 av.setScaleLeftWrapped(true);
203 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
205 assertEquals(wrappedWidth, 24);
208 * adding 3 pixels to width regains one column
211 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
213 assertEquals(wrappedWidth, !Platform.isWin() ? 24 : 25); // 2px not enough
215 wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
217 assertEquals(wrappedWidth, 25); // 3px is enough
220 * turn off scales left and right, make width exactly 157 columns
222 av.setScaleLeftWrapped(false);
223 canvasWidth = al.getWidth() * charWidth;
224 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
225 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
229 * Test the method that computes wrapped width in residues, height of wrapped
230 * widths in pixels, and the number of widths visible
232 @Test(groups = "Functional")
233 public void testCalculateWrappedGeometry_withAnnotations()
235 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
236 "examples/uniref50.fa", DataSourceType.FILE);
237 AlignViewport av = af.getViewport();
238 AlignmentI al = av.getAlignment();
239 assertEquals(al.getWidth(), 157);
240 assertEquals(al.getHeight(), 15);
242 av.setWrapAlignment(true);
243 av.getRanges().setStartEndSeq(0, 14);
244 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
245 int charHeight = av.getCharHeight();
246 int charWidth = av.getCharWidth();
248 assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
249 assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
251 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
254 * first with scales above, left, right
256 av.setShowAnnotation(true);
257 av.setScaleAboveWrapped(true);
258 av.setScaleLeftWrapped(true);
259 av.setScaleRightWrapped(true);
261 FontMetrics fm = testee.getFontMetrics(av.getFont());
262 int labelWidth = fm.stringWidth("000") + charWidth;
263 assertEquals(labelWidth,
264 !Platform.isWin() ? 3 * 9 + charWidth : 3 * 8 + charWidth);
266 int annotationHeight = testee.getAnnotationHeight();
269 * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
270 * take the whole multiple of character widths
272 int canvasWidth = 400;
273 int canvasHeight = 300;
274 int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
275 int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
276 assertEquals(wrappedWidth, residueColumns);
277 assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
278 assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
279 assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
281 int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
282 assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
283 + SeqCanvas.SEQS_ANNOTATION_GAP + annotationHeight);
284 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
287 * repeat height is 17 * (2 + 15) = 289 + 3 + annotationHeight = 510
288 * make canvas height 2 of these plus 3 charHeights
289 * so just enough to draw 2 widths, gap + scale + the first sequence of a third
291 canvasHeight = charHeight * (17 * 2 + 3)
292 + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP);
293 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
294 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
297 * reduce canvas height by 1 pixel - should not be enough height
301 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
302 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
305 * turn off scale above - can now fit in 2 and a bit widths
307 av.setScaleAboveWrapped(false);
308 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
309 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
312 * reduce height to enough for 2 widths and not quite a third
313 * i.e. two repeating heights + spacer + sequence - 1 pixel
315 canvasHeight = charHeight * (16 * 2 + 2)
316 + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP) - 1;
317 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
318 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
321 * add 1 pixel to height - should now get 3 widths drawn
324 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
325 assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
329 * Test simulates loading an unwrapped alignment, shrinking it vertically so
330 * not all sequences are visible, then changing to wrapped mode. The ranges
331 * endSeq should be unchanged, but the vertical repeat height should include
334 @Test(groups = "Functional")
335 public void testCalculateWrappedGeometry_fromScrolled()
337 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
338 "examples/uniref50.fa", DataSourceType.FILE);
340 System.out.println("ap dim = " + af.alignPanel.getSize());
341 System.out.println("seqpan dim = " + af.alignPanel.getSeqPanel().getSize());
342 System.out.println("seqcan dim = " + af.alignPanel.getSeqPanel().seqCanvas.getSize());
345 AlignViewport av = af.getViewport();
346 AlignmentI al = av.getAlignment();
347 assertEquals(al.getWidth(), 157);
348 assertEquals(al.getHeight(), 15);
350 ViewportRanges ranges = av.getRanges();
351 System.out.println(ranges + " before setting to 3");
352 ranges.setStartEndSeq(0, 3);
353 int endSeq = ranges.getEndSeq();
354 System.out.println(ranges + " after setting to 3");
355 av.setShowAnnotation(false);
356 av.setScaleAboveWrapped(true);
358 SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
359 av.setWrapAlignment(true);
360 av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
361 int charHeight = av.getCharHeight();
362 int charWidth = av.getCharWidth();
363 // Windows h=19, w=11.
364 assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
365 assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
367 int canvasWidth = 400;
368 int canvasHeight = 300;
369 testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
370 System.out.println(ranges);
371 assertEquals(ranges.getEndSeq(), endSeq); // unchanged
372 int repeatingHeight = (int) PA.getValue(testee,
373 "wrappedRepeatHeightPx");
374 int h = charHeight * (2 + al.getHeight());
375 assertEquals(repeatingHeight, h);
377 @Test(groups = "Functional")
378 public void testClear_HighlightAndSelection()
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.");