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