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