JAL-3446 unused imports removed
[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 java.awt.Font;
30 import java.awt.FontMetrics;
31
32 import org.testng.annotations.BeforeClass;
33 import org.testng.annotations.Test;
34
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;
44
45 public class SeqCanvasTest
46 {
47   @BeforeClass(alwaysRun = true)
48   public void setUp()
49   {
50     Cache.loadProperties(null);
51     Cache.initLogger();
52     Desktop.getInstance().setVisible(false);
53   }
54
55   /**
56    * Test the method that computes wrapped width in residues, height of wrapped
57    * widths in pixels, and the number of widths visible
58    */
59   @Test(groups = "Functional")
60   public void testCalculateWrappedGeometry_noAnnotations()
61   {
62     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
63             "examples/uniref50.fa", DataSourceType.FILE);
64     
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);
70
71     SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
72
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);
79
80     /*
81      * first with scales above, left, right
82      */
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);
91
92     /*
93      * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
94      * take the whole multiple of character widths
95      */
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"),
104             2 * charHeight);
105     int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
106     assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
107     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
108
109     /*
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
113      */
114     canvasHeight = charHeight * (17 * 2 + 3);
115     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
116     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
117
118     /*
119      * reduce canvas height by 1 pixel 
120      * - should not be enough height to draw 3 widths
121      */
122     canvasHeight -= 1;
123     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
124     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
125
126     /*
127      * turn off scale above - can now fit in 2 and a bit widths
128      */
129     av.setScaleAboveWrapped(false);
130     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
131     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
132
133     /*
134      * reduce height to enough for 2 widths and not quite a third
135      * i.e. two repeating heights + spacer + sequence - 1 pixel
136      */
137     canvasHeight = charHeight * (16 * 2 + 2) - 1;
138     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
139     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
140
141     /*
142      * make canvas width enough for scales and 20 residues
143      */
144     canvasWidth = 2 * labelWidth + 20 * charWidth;
145     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
146             canvasHeight);
147     assertEquals(wrappedWidth, 20);
148
149     /*
150      * reduce width by 1 pixel - rounds down to 19 residues
151      */
152     canvasWidth -= 1;
153     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
154             canvasHeight);
155     assertEquals(wrappedWidth, 19);
156
157     /*
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
160      */
161     av.setScaleLeftWrapped(false);
162     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
163             canvasHeight);
164     assertEquals(wrappedWidth, 23);
165
166     /*
167      * add 10 pixels to width to fit in another whole residue column
168      */
169     canvasWidth += 9;
170     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
171             canvasHeight);
172     assertEquals(wrappedWidth, 23);
173     canvasWidth += 1;
174     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
175             canvasHeight);
176     assertEquals(wrappedWidth, 24);
177
178     /*
179      * turn off East scale to gain 39 more pixels (3 columns remainder 3)
180      */
181     av.setScaleRightWrapped(false);
182     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
183             canvasHeight);
184     assertEquals(wrappedWidth, 27);
185
186     /*
187      * add 9 pixels to width to gain a residue column
188      */
189     canvasWidth += 8;
190     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
191             canvasHeight);
192     assertEquals(wrappedWidth, 27); // 8px not enough
193     canvasWidth += 1;
194     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
195             canvasHeight);
196     assertEquals(wrappedWidth, 28); // 9px is enough
197
198     /*
199      * now West but not East scale - lose 39 pixels or 4 columns
200      */
201     av.setScaleLeftWrapped(true);
202     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
203             canvasHeight);
204     assertEquals(wrappedWidth, 24);
205
206     /*
207      * adding 3 pixels to width regains one column
208      */
209     canvasWidth += 2;
210     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
211             canvasHeight);
212     assertEquals(wrappedWidth, !Platform.isWin() ? 24 : 25); // 2px not enough
213     canvasWidth += 1;
214     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
215             canvasHeight);
216     assertEquals(wrappedWidth, 25); // 3px is enough
217
218     /*
219      * turn off scales left and right, make width exactly 157 columns
220      */
221     av.setScaleLeftWrapped(false);
222     canvasWidth = al.getWidth() * charWidth;
223     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
224     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
225   }
226
227   /**
228    * Test the method that computes wrapped width in residues, height of wrapped
229    * widths in pixels, and the number of widths visible
230    */
231   @Test(groups = "Functional")
232   public void testCalculateWrappedGeometry_withAnnotations()
233   {
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);
240   
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();
246
247     assertEquals(charHeight, !Platform.isWin() ? 17 : 19);
248     assertEquals(charWidth, !Platform.isWin() ? 12 : 11);
249
250     SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
251   
252     /*
253      * first with scales above, left, right
254      */
255     av.setShowAnnotation(true);
256     av.setScaleAboveWrapped(true);
257     av.setScaleLeftWrapped(true);
258     av.setScaleRightWrapped(true);
259
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);
264
265     int annotationHeight = testee.getAnnotationHeight();
266
267     /*
268      * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
269      * take the whole multiple of character widths
270      */
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"),
279             2 * charHeight);
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);
284   
285     /*
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
289      */
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);
294   
295     /*
296      * reduce canvas height by 1 pixel - should not be enough height
297      * to draw 3 widths
298      */
299     canvasHeight -= 1;
300     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
301     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
302   
303     /*
304      * turn off scale above - can now fit in 2 and a bit widths
305      */
306     av.setScaleAboveWrapped(false);
307     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
308     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
309   
310     /*
311      * reduce height to enough for 2 widths and not quite a third
312      * i.e. two repeating heights + spacer + sequence - 1 pixel
313      */
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);
318
319     /*
320      * add 1 pixel to height - should now get 3 widths drawn
321      */
322     canvasHeight += 1;
323     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
324     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
325   }
326
327   /**
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
331    * all sequences.
332    */
333   @Test(groups = "Functional")
334   public void testCalculateWrappedGeometry_fromScrolled()
335   {
336     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
337             "examples/uniref50.fa", DataSourceType.FILE);
338     // 
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());
342
343
344     AlignViewport av = af.getViewport();
345     AlignmentI al = av.getAlignment();
346     assertEquals(al.getWidth(), 157);
347     assertEquals(al.getHeight(), 15);
348
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);
356
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);
365     
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);
375   }
376   @Test(groups = "Functional")
377   public void testClear_HighlightAndSelection()
378   {
379     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
380             "examples/uniref50.fa", DataSourceType.FILE);
381     AlignViewport av = af.getViewport();
382     SearchResultsI highlight = new SearchResults();
383     highlight.addResult(
384             av.getAlignment().getSequenceAt(1).getDatasetSequence(), 50,
385             80);
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.");
397   }
398 }