JAL-3746 apply copyright to tests
[jalview.git] / test / jalview / viewmodel / ViewportRangesTest.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.viewmodel;
22
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertFalse;
25 import static org.testng.Assert.assertTrue;
26
27 import jalview.analysis.AlignmentGenerator;
28 import jalview.datamodel.AlignmentI;
29 import jalview.datamodel.ColumnSelection;
30 import jalview.datamodel.HiddenColumns;
31 import jalview.datamodel.HiddenSequences;
32
33 import java.beans.PropertyChangeEvent;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.List;
38
39 import org.testng.annotations.BeforeClass;
40 import org.testng.annotations.BeforeMethod;
41 import org.testng.annotations.Test;
42
43 public class ViewportRangesTest
44 {
45
46   AlignmentGenerator gen = new AlignmentGenerator(false);
47
48   AlignmentI al = gen.generate(20, 30, 1, 5, 5);
49
50   AlignmentI smallAl = gen.generate(7, 2, 2, 5, 5);
51
52   @BeforeClass(alwaysRun = true)
53   public void setUp()
54   {
55     gen = new AlignmentGenerator(false);
56     al = gen.generate(20, 30, 1, 5, 5);
57     smallAl = gen.generate(7, 2, 2, 5, 5);
58   }
59
60   @BeforeMethod(alwaysRun = true)
61   public void cleanUp()
62   {
63     ColumnSelection sel = new ColumnSelection();
64     al.getHiddenColumns().revealAllHiddenColumns(sel);
65     al.getHiddenSequences().showAll(null);
66     smallAl.getHiddenColumns().revealAllHiddenColumns(sel);
67     smallAl.getHiddenSequences().showAll(null);
68   }
69
70   @Test(groups = { "Functional" })
71   public void testViewportRanges()
72   {
73     ViewportRanges vr = new ViewportRanges(al);
74
75     assertEquals(vr.getStartRes(), 0);
76     assertEquals(vr.getEndRes(), al.getWidth() - 1);
77     assertEquals(vr.getStartSeq(), 0);
78     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
79   }
80
81   @Test(groups = { "Functional" })
82   public void testGetAbsoluteAlignmentHeight()
83   {
84     ViewportRanges vr = new ViewportRanges(al);
85
86     assertEquals(vr.getAbsoluteAlignmentHeight(), al.getHeight());
87
88     al.getHiddenSequences().hideSequence(al.getSequenceAt(3));
89     assertEquals(vr.getAbsoluteAlignmentHeight(), al.getHeight() + 1);
90   }
91
92   @Test(groups = { "Functional" })
93   public void testGetAbsoluteAlignmentWidth()
94   {
95     ViewportRanges vr = new ViewportRanges(al);
96     assertEquals(vr.getAbsoluteAlignmentWidth(), al.getWidth());
97   }
98
99   @Test(groups = { "Functional" })
100   public void testSetEndSeq()
101   {
102     ViewportRanges vr = new ViewportRanges(al);
103     vr.setEndSeq(-1);
104     assertEquals(vr.getEndSeq(), 0);
105
106     vr.setEndSeq(al.getHeight());
107     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
108
109     vr.setEndSeq(al.getHeight() - 1);
110     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
111   }
112
113   @Test(groups = { "Functional" })
114   public void testSetStartRes()
115   {
116     ViewportRanges vr = new ViewportRanges(al);
117     vr.setStartRes(-1);
118     assertEquals(vr.getStartRes(), 0);
119
120     vr.setStartRes(al.getWidth());
121     assertEquals(vr.getStartRes(), al.getWidth() - 1);
122
123     vr.setStartRes(al.getWidth() - 1);
124     assertEquals(vr.getStartRes(), al.getWidth() - 1);
125   }
126
127   @Test(groups = { "Functional" })
128   public void testSetStartSeq()
129   {
130     ViewportRanges vr = new ViewportRanges(al);
131     vr.setStartSeq(-1);
132     assertEquals(vr.getStartSeq(), 0);
133
134     vr.setStartSeq(al.getHeight() - vr.getViewportHeight() + 1);
135     assertEquals(vr.getStartSeq(), al.getHeight() - vr.getViewportHeight());
136
137     vr.setStartSeq(al.getHeight() - vr.getViewportHeight());
138     assertEquals(vr.getStartSeq(), al.getHeight() - vr.getViewportHeight());
139   }
140
141   @Test(groups = { "Functional" })
142   public void testSetStartEndRes()
143   {
144     ViewportRanges vr = new ViewportRanges(al);
145     vr.setStartEndRes(-1, -1);
146     assertEquals(vr.getStartRes(), 0);
147     assertEquals(vr.getEndRes(), 0);
148
149     vr.setStartEndRes(5, 19);
150     assertEquals(vr.getStartRes(), 5);
151     assertEquals(vr.getEndRes(), 19);
152
153     vr.setStartEndRes(al.getWidth(), al.getWidth());
154     assertEquals(vr.getEndRes(), al.getWidth() - 1);
155
156     ViewportRanges vrsmall = new ViewportRanges(smallAl);
157     vrsmall.setStartEndRes(al.getWidth(), al.getWidth());
158     assertEquals(vrsmall.getEndRes(), 6);
159
160     // make visible alignment width = 0
161     smallAl.getHiddenColumns().hideColumns(0, 6);
162     vrsmall.setStartEndRes(0, 4);
163     assertEquals(vrsmall.getStartRes(), 0);
164     assertEquals(vrsmall.getEndRes(), 0);
165   }
166
167   @Test(groups = { "Functional" })
168   public void testSetStartEndSeq()
169   {
170     ViewportRanges vr = new ViewportRanges(al);
171     vr.setStartEndSeq(-1, -1);
172     assertEquals(vr.getStartSeq(), 0);
173     assertEquals(vr.getEndSeq(), 0);
174
175     vr.setStartEndSeq(5, 19);
176     assertEquals(vr.getStartSeq(), 5);
177     assertEquals(vr.getEndSeq(), 19);
178
179     vr.setStartEndSeq(al.getHeight(), al.getHeight());
180     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
181
182     // make visible alignment height = 0
183     smallAl.getHiddenSequences().hideSequence(smallAl.getSequenceAt(0));
184     smallAl.getHiddenSequences().hideSequence(smallAl.getSequenceAt(0));
185     ViewportRanges vrsmall = new ViewportRanges(smallAl);
186     vrsmall.setStartEndSeq(0, 3);
187     assertEquals(vrsmall.getStartSeq(), 0);
188     assertEquals(vrsmall.getEndSeq(), 0);
189   }
190
191   @Test(groups = { "Functional" })
192   public void testSetStartResAndSeq()
193   {
194     ViewportRanges vr = new ViewportRanges(al);
195     vr.setViewportHeight(10);
196     vr.setStartResAndSeq(3, 6);
197     assertEquals(vr.getStartRes(), 3);
198     assertEquals(vr.getStartSeq(), 6);
199     assertEquals(vr.getEndRes(), 3 + vr.getViewportWidth() - 1);
200     assertEquals(vr.getEndSeq(), 6 + vr.getViewportHeight() - 1);
201
202     vr.setStartResAndSeq(10, 25);
203     assertEquals(vr.getStartRes(), 10);
204     assertEquals(vr.getStartSeq(), 19);
205     assertEquals(vr.getEndRes(), 10 + vr.getViewportWidth() - 1);
206     assertEquals(vr.getEndSeq(), 19 + vr.getViewportHeight() - 1);
207   }
208
209   @Test(groups = { "Functional" })
210   public void testSetViewportHeight()
211   {
212     ViewportRanges vr = new ViewportRanges(al);
213     vr.setViewportHeight(13);
214     assertEquals(vr.getViewportHeight(), 13);
215   }
216
217   @Test(groups = { "Functional" })
218   public void testSetViewportWidth()
219   {
220     ViewportRanges vr = new ViewportRanges(al);
221     vr.setViewportWidth(13);
222     assertEquals(vr.getViewportWidth(), 13);
223   }
224
225   @Test(groups = { "Functional" })
226   public void testSetViewportStartAndHeight()
227   {
228     ViewportRanges vr = new ViewportRanges(al);
229     vr.setViewportStartAndHeight(2, 6);
230     assertEquals(vr.getViewportHeight(), 6);
231     assertEquals(vr.getStartSeq(), 2);
232
233     // reset -ve values of start to 0
234     vr.setViewportStartAndHeight(-1, 7);
235     assertEquals(vr.getViewportHeight(), 7);
236     assertEquals(vr.getStartSeq(), 0);
237
238     // reset out of bounds start values to within bounds
239     vr.setViewportStartAndHeight(35, 5);
240     assertEquals(vr.getViewportHeight(), 5);
241     assertEquals(vr.getStartSeq(), 24);
242   }
243
244   @Test(groups = { "Functional" })
245   public void testSetViewportStartAndWidth()
246   {
247     ViewportRanges vr = new ViewportRanges(al);
248     vr.setViewportStartAndWidth(2, 6);
249     assertEquals(vr.getViewportWidth(), 6);
250     assertEquals(vr.getStartRes(), 2);
251
252     // reset -ve values of start to 0
253     vr.setViewportStartAndWidth(-1, 7);
254     assertEquals(vr.getViewportWidth(), 7);
255     assertEquals(vr.getStartRes(), 0);
256
257     // reset out of bounds start values to within bounds
258     vr.setViewportStartAndWidth(35, 5);
259     assertEquals(vr.getViewportWidth(), 5);
260     assertEquals(vr.getStartRes(), 16);
261
262     // small alignment doesn't get bounds reset
263     ViewportRanges vrsmall = new ViewportRanges(smallAl);
264     vrsmall.setViewportStartAndWidth(0, 63);
265     assertEquals(vrsmall.getViewportWidth(), 7);
266     assertEquals(vrsmall.getStartRes(), 0);
267   }
268
269   @Test(groups = { "Functional" })
270   public void testPageUpDown()
271   {
272     ViewportRanges vr = new ViewportRanges(al);
273     vr.setViewportStartAndHeight(8, 6);
274     vr.pageDown();
275     assertEquals(vr.getStartSeq(), 13);
276
277     vr.pageUp();
278     assertEquals(vr.getStartSeq(), 8);
279
280     vr.pageUp();
281     assertEquals(vr.getStartSeq(), 3);
282
283     vr.pageUp();
284     // pageup does not go beyond 0, viewport height stays the same
285     assertEquals(vr.getStartSeq(), 0);
286     assertEquals(vr.getViewportHeight(), 6);
287
288     vr.pageDown();
289     vr.pageDown();
290     vr.pageDown();
291     vr.pageDown();
292     vr.pageDown();
293
294     // pagedown to bottom does not go beyond end, and height stays same
295     assertEquals(vr.getStartSeq(), 24);
296     assertEquals(vr.getViewportHeight(), 6);
297   }
298
299   @Test(groups = { "Functional" })
300   public void testScrollUp()
301   {
302     ViewportRanges vr = new ViewportRanges(al);
303     vr.setViewportStartAndHeight(1, 5);
304     vr.scrollUp(true);
305     assertEquals(vr.getStartSeq(), 0);
306     // can't scroll above top
307     vr.scrollUp(true);
308     assertEquals(vr.getStartSeq(), 0);
309
310     vr.setViewportStartAndHeight(24, 5);
311     vr.scrollUp(false);
312     assertEquals(vr.getStartSeq(), 25);
313     // can't scroll beyond bottom
314     vr.scrollUp(false);
315     assertEquals(vr.getStartSeq(), 25);
316   }
317
318   @Test(groups = { "Functional" })
319   public void testScrollUpWithHidden()
320   {
321     ViewportRanges vr = new ViewportRanges(al);
322
323     // hide last sequence
324     HiddenSequences hidden = new HiddenSequences(al);
325     hidden.hideSequence(al.getSequenceAt(29));
326
327     vr.setViewportStartAndHeight(1, 5);
328     vr.scrollUp(true);
329     assertEquals(vr.getStartSeq(), 0);
330     // can't scroll above top
331     vr.scrollUp(true);
332     assertEquals(vr.getStartSeq(), 0);
333
334     vr.setViewportStartAndHeight(23, 5);
335     vr.scrollUp(false);
336     assertEquals(vr.getStartSeq(), 24);
337     // can't scroll beyond bottom
338     vr.scrollUp(false);
339     assertEquals(vr.getStartSeq(), 24);
340   }
341
342   @Test(groups = { "Functional" })
343   public void testScrollRight()
344   {
345     ViewportRanges vr = new ViewportRanges(al);
346     vr.setViewportStartAndWidth(1, 5);
347     vr.scrollRight(false);
348     assertEquals(vr.getStartRes(), 0);
349     // can't scroll left past start
350     vr.scrollRight(false);
351     assertEquals(vr.getStartRes(), 0);
352
353     vr.setViewportStartAndWidth(15, 5);
354     vr.scrollRight(true);
355     assertEquals(vr.getStartRes(), 16);
356     // can't scroll right past end
357     vr.scrollRight(true);
358     assertEquals(vr.getStartRes(), 16);
359   }
360
361   @Test(groups = { "Functional" })
362   public void testScrollRightWithHidden()
363   {
364     ViewportRanges vr = new ViewportRanges(al);
365
366     // hide last 2 columns
367     HiddenColumns cols = new HiddenColumns();
368     cols.hideColumns(19, 20);
369     al.setHiddenColumns(cols);
370
371     vr.setViewportStartAndWidth(1, 5);
372     vr.scrollRight(false);
373     assertEquals(vr.getStartRes(), 0);
374     // can't scroll left past start
375     vr.scrollRight(false);
376     assertEquals(vr.getStartRes(), 0);
377
378     vr.setViewportStartAndWidth(13, 5);
379     vr.scrollRight(true);
380     assertEquals(vr.getStartRes(), 14);
381     // can't scroll right past last visible col
382     vr.scrollRight(true);
383     assertEquals(vr.getStartRes(), 14);
384   }
385
386   @Test(groups = { "Functional" })
387   public void testScrollToWrappedVisible()
388   {
389     AlignmentI al2 = gen.generate(60, 30, 1, 5, 5);
390
391     ViewportRanges vr = new ViewportRanges(al2);
392
393     // start with viewport on 5-14
394     vr.setViewportStartAndWidth(5, 10);
395     assertEquals(vr.getStartRes(), 5);
396     assertEquals(vr.getEndRes(), 14);
397
398     // scroll to 12 - no change
399     assertFalse(vr.scrollToWrappedVisible(12));
400     assertEquals(vr.getStartRes(), 5);
401
402     // scroll to 2 - back to 0-9
403     assertTrue(vr.scrollToWrappedVisible(2));
404     assertEquals(vr.getStartRes(), 0);
405     assertEquals(vr.getEndRes(), 9);
406
407     // scroll to 9 - no change
408     assertFalse(vr.scrollToWrappedVisible(9));
409     assertEquals(vr.getStartRes(), 0);
410
411     // scroll to 12 - moves to 10-19
412     assertTrue(vr.scrollToWrappedVisible(12));
413     assertEquals(vr.getStartRes(), 10);
414     assertEquals(vr.getEndRes(), 19);
415
416     vr.setStartRes(13);
417     assertEquals(vr.getStartRes(), 13);
418     assertEquals(vr.getEndRes(), 22);
419
420     // scroll to 45 - jumps to 43-52
421     assertTrue(vr.scrollToWrappedVisible(45));
422     assertEquals(vr.getStartRes(), 43);
423     assertEquals(vr.getEndRes(), 52);
424   }
425
426   @Test(groups = { "Functional" })
427   public void testScrollToVisible()
428   {
429     ViewportRanges vr = new ViewportRanges(al);
430     vr.setViewportStartAndWidth(12, 5);
431     vr.setViewportStartAndHeight(10, 6);
432     vr.scrollToVisible(13, 14);
433
434     // no change
435     assertEquals(vr.getStartRes(), 12);
436     assertEquals(vr.getStartSeq(), 10);
437
438     vr.scrollToVisible(5, 6);
439     assertEquals(vr.getStartRes(), 5);
440     assertEquals(vr.getStartSeq(), 6);
441
442     // test for hidden columns too
443     al.getHiddenColumns().hideColumns(1, 3);
444     vr.scrollToVisible(13, 3);
445     assertEquals(vr.getStartRes(), 6);
446     assertEquals(vr.getStartSeq(), 3);
447
448     vr.scrollToVisible(2, 9);
449     assertEquals(vr.getStartRes(), 0);
450     assertEquals(vr.getStartSeq(), 4);
451   }
452
453   @Test(groups = { "Functional" })
454   public void testEventFiring()
455   {
456     ViewportRanges vr = new ViewportRanges(al);
457     MockPropChangeListener l = new MockPropChangeListener(vr);
458     List<String> emptylist = new ArrayList<>();
459
460     vr.setViewportWidth(5);
461     vr.setViewportHeight(5);
462     l.reset();
463
464     // one event fired when startRes is called with new value
465     vr.setStartRes(4);
466     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
467     l.reset();
468
469     // no event fired for same value
470     vr.setStartRes(4);
471     assertTrue(l.verify(0, emptylist));
472     l.reset();
473
474     vr.setStartSeq(4);
475     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
476     l.reset();
477
478     vr.setStartSeq(4);
479     assertTrue(l.verify(0, emptylist));
480     l.reset();
481
482     vr.setEndSeq(10);
483     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
484     l.reset();
485
486     vr.setEndSeq(10);
487     assertTrue(l.verify(0, emptylist));
488     l.reset();
489
490     vr.setStartEndRes(2, 15);
491     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
492     l.reset();
493
494     vr.setStartEndRes(2, 15);
495     assertTrue(l.verify(0, emptylist));
496     l.reset();
497
498     // check new value fired by event is corrected startres
499     vr.setStartEndRes(-1, 5);
500     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES),
501             Arrays.asList(0)));
502     l.reset();
503
504     // check new value fired by event is corrected endres
505     vr.setStartEndRes(0, -1);
506     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDRES),
507             Arrays.asList(0)));
508     l.reset();
509
510     vr.setStartEndSeq(2, 15);
511     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
512     l.reset();
513
514     vr.setStartEndSeq(2, 15);
515     assertTrue(l.verify(0, emptylist));
516     l.reset();
517
518     vr.setStartEndRes(2, 2); // so seq and res values should be different, in
519                              // case of transposing in code
520     l.reset();
521
522     // check new value fired by event is corrected startseq
523     vr.setStartEndSeq(-1, 5);
524     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ),
525             Arrays.asList(0)));
526     l.reset();
527
528     // check new value fired by event is corrected endseq
529     vr.setStartEndSeq(0, -1);
530     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ),
531             Arrays.asList(0)));
532     l.reset();
533
534     // reset for later tests
535     vr.setStartEndSeq(2, 15);
536     l.reset();
537
538     // test viewport height and width setting triggers event
539     vr.setViewportHeight(10);
540     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ)));
541     l.reset();
542
543     vr.setViewportWidth(18);
544     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDRES)));
545     l.reset();
546
547     // already has seq start set to 2, so triggers endseq
548     vr.setViewportStartAndHeight(2, 16);
549     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ)));
550     l.reset();
551
552     vr.setViewportStartAndWidth(1, 14);
553     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
554     l.reset();
555
556     // test page up/down triggers event
557     vr.pageUp();
558     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
559     l.reset();
560
561     vr.pageDown();
562     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
563     l.reset();
564
565     // test scrolling triggers event
566     vr.scrollUp(true);
567     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
568     l.reset();
569
570     vr.scrollUp(false);
571     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
572     l.reset();
573
574     vr.scrollRight(true);
575     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
576     l.reset();
577
578     vr.scrollRight(false);
579     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
580     l.reset();
581
582     vr.scrollToVisible(10, 10);
583     assertTrue(l.verify(4,
584             Arrays.asList(ViewportRanges.STARTSEQ, ViewportRanges.STARTSEQ,
585                     ViewportRanges.STARTSEQ, ViewportRanges.STARTSEQ)));
586     l.reset();
587
588     /*
589      * scrollToWrappedVisible does nothing if the target position is
590      * within the current startRes-endRes range
591      */
592     assertFalse(vr.scrollToWrappedVisible(5));
593     assertTrue(l.verify(0, Collections.<String> emptyList()));
594     l.reset();
595
596     vr.scrollToWrappedVisible(25);
597     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
598     l.reset();
599
600     // test setStartResAndSeq triggers one event
601     vr.setStartResAndSeq(5, 7);
602     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRESANDSEQ),
603             Arrays.asList(5, 7)));
604
605     l.reset();
606   }
607
608   @Test(groups = { "Functional" })
609   public void testGetWrappedScrollPosition()
610   {
611     AlignmentI al2 = gen.generate(157, 15, 1, 5, 5);
612     ViewportRanges vr = new ViewportRanges(al2);
613     vr.setStartEndRes(0, 39);
614     int width = vr.getViewportWidth(); // 40
615
616     /*
617      * scroll is 0 at column 0 (only)
618      */
619     assertEquals(vr.getWrappedScrollPosition(0), 0);
620
621     /*
622      * scroll is 1 at columns 1-40
623      */
624     int i = 1;
625     int j = width;
626     for (; i <= j; i++)
627     {
628       assertEquals(1, vr.getWrappedScrollPosition(i));
629     }
630
631     /*
632      * scroll is 2 at columns 41-80, etc
633      */
634     j += width;
635     for (; i <= j; i++)
636     {
637       assertEquals(2, vr.getWrappedScrollPosition(i), "For " + i);
638     }
639   }
640
641   @Test(groups = { "Functional" })
642   public void testPageUpDownWrapped()
643   {
644     /*
645      * 15 sequences, 110 residues wide (+gaps)
646      */
647     AlignmentI al2 = gen.generate(110, 15, 1, 5, 5);
648
649     ViewportRanges vr = new ViewportRanges(al2);
650     vr.setWrappedMode(true);
651
652     // first row
653     vr.setViewportStartAndWidth(0, 40);
654     int width = vr.getViewportWidth();
655     assertEquals(width, 40);
656     assertEquals(vr.getStartRes(), 0);
657     assertEquals(vr.getEndRes(), 39);
658     assertEquals(vr.getStartSeq(), 0);
659     assertEquals(vr.getEndSeq(), 14);
660
661     // second row
662     vr.pageDown();
663     assertEquals(vr.getStartRes(), 40);
664     assertEquals(vr.getEndRes(), 79);
665     assertEquals(vr.getStartSeq(), 0);
666     assertEquals(vr.getEndSeq(), 14);
667
668     // third and last row
669     // note endRes is nominal (>width) to preserve viewport width
670     vr.pageDown();
671     assertEquals(vr.getStartRes(), 80);
672     assertEquals(vr.getEndRes(), 119);
673     assertEquals(vr.getStartSeq(), 0);
674     assertEquals(vr.getEndSeq(), 14);
675
676     // another pageDown should do nothing
677     vr.pageDown();
678     assertEquals(vr.getStartRes(), 80);
679     assertEquals(vr.getEndRes(), 119);
680     assertEquals(vr.getStartSeq(), 0);
681     assertEquals(vr.getEndSeq(), 14);
682
683     // back to second row
684     vr.pageUp();
685     assertEquals(vr.getStartRes(), 40);
686     assertEquals(vr.getEndRes(), 79);
687     assertEquals(vr.getStartSeq(), 0);
688     assertEquals(vr.getEndSeq(), 14);
689
690     // back to first row
691     vr.pageUp();
692     assertEquals(vr.getStartRes(), 0);
693     assertEquals(vr.getEndRes(), 39);
694     assertEquals(vr.getStartSeq(), 0);
695     assertEquals(vr.getEndSeq(), 14);
696
697     // another pageUp should do nothing
698     vr.pageUp();
699     assertEquals(vr.getStartRes(), 0);
700     assertEquals(vr.getEndRes(), 39);
701     assertEquals(vr.getStartSeq(), 0);
702     assertEquals(vr.getEndSeq(), 14);
703
704     /*
705      * simulate scroll right a few positions
706      */
707     vr.setStartRes(5);
708     assertEquals(vr.getStartRes(), 5);
709     assertEquals(vr.getEndRes(), 5 + width - 1); // 44
710
711     vr.pageDown(); // 5-44 shifts to 45-84
712     assertEquals(vr.getStartRes(), 45);
713     assertEquals(vr.getEndRes(), 84);
714
715     vr.pageDown(); // 45-84 shifts to 85-124
716     assertEquals(vr.getStartRes(), 85);
717     assertEquals(vr.getEndRes(), 124);
718
719     vr.pageDown(); // no change - at end already
720     assertEquals(vr.getStartRes(), 85);
721     assertEquals(vr.getEndRes(), 124);
722
723     vr.pageUp(); // back we go
724     assertEquals(vr.getStartRes(), 45);
725     assertEquals(vr.getEndRes(), 84);
726
727     vr.pageUp();
728     assertEquals(vr.getStartRes(), 5);
729     assertEquals(vr.getEndRes(), 44);
730
731     vr.pageUp(); // back to the start
732     assertEquals(vr.getStartRes(), 0);
733     assertEquals(vr.getEndRes(), 39);
734   }
735
736   @Test(groups = { "Functional" })
737   public void testSetStartEndResWrapped()
738   {
739     ViewportRanges vr = new ViewportRanges(al);
740     vr.setWrappedMode(true);
741     vr.setStartEndRes(-1, -1);
742     assertEquals(vr.getStartRes(), 0);
743     assertEquals(vr.getEndRes(), 0);
744
745     vr.setStartEndRes(5, 19);
746     assertEquals(vr.getStartRes(), 5);
747     assertEquals(vr.getEndRes(), 19);
748
749     // bounds are not constrained to alignment width
750     // when in wrapped mode
751     vr.setStartEndRes(88, 888);
752     assertEquals(vr.getStartRes(), 88);
753     assertEquals(vr.getEndRes(), 888);
754
755     ViewportRanges vrsmall = new ViewportRanges(smallAl);
756     vrsmall.setWrappedMode(true);
757     vrsmall.setStartEndRes(88, 888);
758     assertEquals(vrsmall.getStartRes(), 88);
759     assertEquals(vrsmall.getEndRes(), 888);
760
761     // make visible alignment width = 0
762     smallAl.getHiddenColumns().hideColumns(0, 6);
763     vrsmall.setStartEndRes(0, 4);
764     assertEquals(vrsmall.getStartRes(), 0);
765     assertEquals(vrsmall.getEndRes(), 4);
766   }
767
768   @Test(groups = { "Functional" })
769   public void testSetViewportStartAndWidthWrapped()
770   {
771     ViewportRanges vr = new ViewportRanges(al);
772     vr.setWrappedMode(true);
773     vr.setViewportStartAndWidth(2, 6);
774     assertEquals(vr.getViewportWidth(), 6);
775     assertEquals(vr.getStartRes(), 2);
776
777     // reset -ve values of start to 0
778     vr.setViewportStartAndWidth(-1, 7);
779     assertEquals(vr.getViewportWidth(), 7);
780     assertEquals(vr.getStartRes(), 0);
781
782     // out of bounds values are not forced to within bounds
783     vr.setViewportStartAndWidth(35, 5);
784     assertEquals(vr.getViewportWidth(), 5);
785     assertEquals(vr.getStartRes(), 35);
786
787     // small alignment doesn't get bounds reset
788     ViewportRanges vrsmall = new ViewportRanges(smallAl);
789     vrsmall.setViewportStartAndWidth(0, 63);
790     assertEquals(vrsmall.getViewportWidth(), 7);
791     assertEquals(vrsmall.getStartRes(), 0);
792   }
793
794   @Test(groups = { "Functional" })
795   public void testGetWrappedMaxScroll()
796   {
797     // generate an ungapped alignment of width 140
798     int alignmentWidth = 140;
799     AlignmentI al2 = gen.generate(alignmentWidth, 15, 1, 0, 5);
800     ViewportRanges vr = new ViewportRanges(al2);
801     vr.setStartEndRes(0, 39);
802     int width = vr.getViewportWidth(); // 40
803     int partWidth = alignmentWidth % width; // 20
804
805     /*
806      * there are 3 * 40 remainder 20 residues
807      * number of widths depends on offset (scroll right)
808      * 4 widths (maxScroll = 3) if offset by 0 or more than 19 columns
809      * 5 widths (maxScroll = 4) if 1 <= offset <= 19
810      */
811     for (int col = 0; col < alignmentWidth; col++)
812     {
813       int offset = col % width;
814       if (offset > 0 && offset < partWidth)
815       {
816         assertEquals(vr.getWrappedMaxScroll(col), 4, "col " + col);
817       }
818       else
819       {
820         assertEquals(vr.getWrappedMaxScroll(col), 3, "col " + col);
821       }
822     }
823   }
824
825   @Test(groups = { "Functional" })
826   public void testScrollUp_wrapped()
827   {
828     /*
829      * alignment 30 tall and 45 wide
830      */
831     AlignmentI al2 = gen.generate(45, 30, 1, 0, 5);
832
833     /*
834      * wrapped view, 5 sequences high, start at sequence offset 1
835      */
836     ViewportRanges vr = new ViewportRanges(al2);
837     vr.setWrappedMode(true);
838     vr.setViewportStartAndHeight(1, 5);
839
840     /*
841      * offset wrapped view to column 3
842      */
843     vr.setStartEndRes(3, 22);
844
845     int startRes = vr.getStartRes();
846     int width = vr.getViewportWidth();
847     assertEquals(startRes, 3);
848     assertEquals(width, 20);
849
850     // in wrapped mode, we change startRes but not startSeq
851     // scroll down:
852     vr.scrollUp(false);
853     assertEquals(vr.getStartSeq(), 1);
854     assertEquals(vr.getStartRes(), 23);
855
856     // scroll up returns to original position
857     vr.scrollUp(true);
858     assertEquals(vr.getStartSeq(), 1);
859     assertEquals(vr.getStartRes(), 3);
860
861     // scroll up again returns to 'origin'
862     vr.scrollUp(true);
863     assertEquals(vr.getStartSeq(), 1);
864     assertEquals(vr.getStartRes(), 0);
865
866     /*
867      * offset 3 columns once more and do some scroll downs
868      */
869     vr.setStartEndRes(3, 22);
870     vr.scrollUp(false);
871     assertEquals(vr.getStartSeq(), 1);
872     assertEquals(vr.getStartRes(), 23);
873     vr.scrollUp(false);
874     assertEquals(vr.getStartSeq(), 1);
875     assertEquals(vr.getStartRes(), 43);
876
877     /*
878      * scroll down beyond end of alignment does nothing
879      */
880     vr.scrollUp(false);
881     assertEquals(vr.getStartSeq(), 1);
882     assertEquals(vr.getStartRes(), 43);
883   }
884
885   @Test(groups = { "Functional" })
886   public void testSetViewportLocation()
887   {
888     AlignmentI al2 = gen.generate(60, 80, 1, 0, 0);
889
890     ViewportRanges vr = new ViewportRanges(al2);
891
892     // start with viewport on 5-14
893     vr.setViewportStartAndWidth(5, 10);
894     assertEquals(vr.getStartRes(), 5);
895     assertEquals(vr.getEndRes(), 14);
896
897     vr.setViewportStartAndHeight(3, 13);
898     assertEquals(vr.getStartSeq(), 3);
899     assertEquals(vr.getEndSeq(), 15);
900
901     // set location to (8,5) - no change
902     vr.setViewportLocation(8, 5);
903     assertEquals(vr.getStartRes(), 5);
904     assertEquals(vr.getEndRes(), 14);
905     assertEquals(vr.getStartSeq(), 3);
906     assertEquals(vr.getEndSeq(), 15);
907
908     // set location to (40,50) - change to top left (40,50)
909     vr.setViewportLocation(40, 50);
910     assertEquals(vr.getStartRes(), 40);
911     assertEquals(vr.getEndRes(), 49);
912     assertEquals(vr.getStartSeq(), 50);
913     assertEquals(vr.getEndSeq(), 62);
914
915     // set location past end of alignment - resets to leftmost pos
916     vr.setViewportLocation(63, 85);
917     assertEquals(vr.getStartRes(), 50);
918     assertEquals(vr.getEndRes(), 59);
919     assertEquals(vr.getStartSeq(), 67);
920     assertEquals(vr.getEndSeq(), 79);
921
922     // hide some columns
923     al2.getHiddenColumns().hideColumns(20, 50);
924     vr.setViewportLocation(55, 4);
925     assertEquals(vr.getStartRes(), 19);
926     assertEquals(vr.getEndRes(), 28);
927     assertEquals(vr.getStartSeq(), 4);
928     assertEquals(vr.getEndSeq(), 16);
929
930     // hide some sequences
931     al2.getHiddenSequences().hideSequence(al2.getSequenceAt(3));
932     al2.getHiddenSequences().hideSequence(al2.getSequenceAt(4));
933     vr.setViewportLocation(17, 5);
934     assertEquals(vr.getStartRes(), 17);
935     assertEquals(vr.getEndRes(), 26);
936     assertEquals(vr.getStartSeq(), 3);
937     assertEquals(vr.getEndSeq(), 15);
938
939     // set wrapped mode
940     vr.setWrappedMode(true);
941     vr.setViewportLocation(1, 8);
942     assertEquals(vr.getStartRes(), 0);
943     assertEquals(vr.getEndRes(), 9);
944     assertEquals(vr.getStartSeq(), 3);
945     assertEquals(vr.getEndSeq(), 15);
946
947     // try further down the alignment
948     vr.setViewportLocation(57, 5);
949     assertEquals(vr.getStartRes(), 20);
950     assertEquals(vr.getEndRes(), 29);
951     assertEquals(vr.getStartSeq(), 3);
952     assertEquals(vr.getEndSeq(), 15);
953   }
954 }
955
956 // mock listener for property change events
957 class MockPropChangeListener implements ViewportListenerI
958 {
959   private int firecount = 0;
960
961   private List<String> events = new ArrayList<>();
962
963   private List<Integer> newvalues = new ArrayList<>();
964
965   public MockPropChangeListener(ViewportRanges vr)
966   {
967     vr.addPropertyChangeListener(this);
968   }
969
970   @Override
971   public void propertyChange(PropertyChangeEvent evt)
972   {
973     firecount++;
974     events.add(evt.getPropertyName());
975     if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
976     {
977       newvalues.add(((int[]) evt.getNewValue())[0]);
978       newvalues.add(((int[]) evt.getNewValue())[1]);
979     }
980     else
981     {
982       newvalues.add((Integer) evt.getNewValue());
983     }
984   }
985
986   public boolean verify(int count, List<String> eventslist,
987           List<Integer> valueslist)
988   {
989     return (count == firecount) && events.equals(eventslist)
990             && newvalues.equals(valueslist);
991   }
992
993   public boolean verify(int count, List<String> eventslist)
994   {
995     return (count == firecount) && events.equals(eventslist);
996   }
997
998   public void reset()
999   {
1000     firecount = 0;
1001     events.clear();
1002     newvalues.clear();
1003   }
1004 }