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