41a313f2ba26270e8c68f643ae6a4d50715fb00d
[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   @Test(groups = { "Functional" })
406   public void testScrollToVisible()
407   {
408     ViewportRanges vr = new ViewportRanges(al);
409     vr.setViewportStartAndWidth(12,5);
410     vr.setViewportStartAndHeight(10,6);
411     vr.scrollToVisible(13, 14);
412     
413     // no change
414     assertEquals(vr.getStartRes(), 12);
415     assertEquals(vr.getStartSeq(), 10);
416     
417     vr.scrollToVisible(5,6);
418     assertEquals(vr.getStartRes(), 5);
419     assertEquals(vr.getStartSeq(), 6);
420     
421     // test for hidden columns too
422     al.getHiddenColumns().hideColumns(1, 3);
423     vr.scrollToVisible(13, 3);
424     assertEquals(vr.getStartRes(), 6);
425     assertEquals(vr.getStartSeq(), 3);
426
427     vr.scrollToVisible(2, 9);
428     assertEquals(vr.getStartRes(), 0);
429     assertEquals(vr.getStartSeq(), 4);
430   }
431
432   @Test(groups = { "Functional" })
433   public void testEventFiring()
434   {
435     ViewportRanges vr = new ViewportRanges(al);
436     MockPropChangeListener l = new MockPropChangeListener(vr);
437     List<String> emptylist = new ArrayList<>();
438
439     vr.setViewportWidth(5);
440     vr.setViewportHeight(5);
441     l.reset();
442
443     // one event fired when startRes is called with new value
444     vr.setStartRes(4);
445     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
446     l.reset();
447
448     // no event fired for same value
449     vr.setStartRes(4);
450     assertTrue(l.verify(0, emptylist));
451     l.reset();
452
453     vr.setStartSeq(4);
454     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
455     l.reset();
456
457     vr.setStartSeq(4);
458     assertTrue(l.verify(0, emptylist));
459     l.reset();
460
461     vr.setEndSeq(10);
462     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
463     l.reset();
464
465     vr.setEndSeq(10);
466     assertTrue(l.verify(0, emptylist));
467     l.reset();
468
469     vr.setStartEndRes(2, 15);
470     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
471     l.reset();
472
473     vr.setStartEndRes(2, 15);
474     assertTrue(l.verify(0, emptylist));
475     l.reset();
476
477     // check new value fired by event is corrected startres
478     vr.setStartEndRes(-1, 5);
479     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES),
480             Arrays.asList(0)));
481     l.reset();
482
483     // check new value fired by event is corrected endres
484     vr.setStartEndRes(0, -1);
485     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDRES),
486             Arrays.asList(0)));
487     l.reset();
488
489     vr.setStartEndSeq(2, 15);
490     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
491     l.reset();
492
493     vr.setStartEndSeq(2, 15);
494     assertTrue(l.verify(0, emptylist));
495     l.reset();
496
497     vr.setStartEndRes(2, 2); // so seq and res values should be different, in
498                              // case of transposing in code
499     l.reset();
500
501     // check new value fired by event is corrected startseq
502     vr.setStartEndSeq(-1, 5);
503     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ),
504             Arrays.asList(0)));
505     l.reset();
506
507     // check new value fired by event is corrected endseq
508     vr.setStartEndSeq(0, -1);
509     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ),
510             Arrays.asList(0)));
511     l.reset();
512
513     // reset for later tests
514     vr.setStartEndSeq(2, 15);
515     l.reset();
516
517     // test viewport height and width setting triggers event
518     vr.setViewportHeight(10);
519     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ)));
520     l.reset();
521
522     vr.setViewportWidth(18);
523     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDRES)));
524     l.reset();
525
526     // already has seq start set to 2, so triggers endseq
527     vr.setViewportStartAndHeight(2, 16);
528     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.ENDSEQ)));
529     l.reset();
530
531     vr.setViewportStartAndWidth(1, 14);
532     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
533     l.reset();
534
535     // test page up/down triggers event
536     vr.pageUp();
537     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
538     l.reset();
539
540     vr.pageDown();
541     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
542     l.reset();
543
544     // test scrolling triggers event
545     vr.scrollUp(true);
546     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
547     l.reset();
548
549     vr.scrollUp(false);
550     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTSEQ)));
551     l.reset();
552
553     vr.scrollRight(true);
554     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
555     l.reset();
556
557     vr.scrollRight(false);
558     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
559     l.reset();
560
561     vr.scrollToVisible(10, 10);
562     assertTrue(l.verify(4,
563             Arrays.asList(ViewportRanges.STARTSEQ, ViewportRanges.STARTSEQ,
564                     ViewportRanges.STARTSEQ, ViewportRanges.STARTSEQ)));
565     l.reset();
566
567     /*
568      * scrollToWrappedVisible does nothing if the target position is
569      * within the current startRes-endRes range
570      */
571     assertFalse(vr.scrollToWrappedVisible(5));
572     assertTrue(l.verify(0, Collections.<String> emptyList()));
573     l.reset();
574
575     vr.scrollToWrappedVisible(25);
576     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRES)));
577     l.reset();
578
579     // test setStartResAndSeq triggers one event
580     vr.setStartResAndSeq(5, 7);
581     assertTrue(l.verify(1, Arrays.asList(ViewportRanges.STARTRESANDSEQ),
582             Arrays.asList(5, 7)));
583
584     l.reset();
585   }
586
587   @Test(groups = { "Functional" })
588   public void testGetWrappedScrollPosition()
589   {
590     AlignmentI al2 = gen.generate(157, 15, 1, 5, 5);
591     ViewportRanges vr = new ViewportRanges(al2);
592     vr.setStartEndRes(0, 39);
593     int width = vr.getViewportWidth(); // 40
594
595     /*
596      * scroll is 0 at column 0 (only)
597      */
598     assertEquals(vr.getWrappedScrollPosition(0), 0);
599
600     /*
601      * scroll is 1 at columns 1-40
602      */
603     int i = 1;
604     int j = width;
605     for (; i <= j; i++)
606     {
607       assertEquals(1, vr.getWrappedScrollPosition(i));
608     }
609
610     /*
611      * scroll is 2 at columns 41-80, etc
612      */
613     j += width;
614     for (; i <= j; i++)
615     {
616       assertEquals(2, vr.getWrappedScrollPosition(i), "For " + i);
617     }
618   }
619
620   @Test(groups = { "Functional" })
621   public void testPageUpDownWrapped()
622   {
623     /*
624      * 15 sequences, 110 residues wide (+gaps)
625      */
626     AlignmentI al2 = gen.generate(110, 15, 1, 5, 5);
627
628     ViewportRanges vr = new ViewportRanges(al2);
629     vr.setWrappedMode(true);
630
631     // first row
632     vr.setViewportStartAndWidth(0, 40);
633     int width = vr.getViewportWidth();
634     assertEquals(width, 40);
635     assertEquals(vr.getStartRes(), 0);
636     assertEquals(vr.getEndRes(), 39);
637     assertEquals(vr.getStartSeq(), 0);
638     assertEquals(vr.getEndSeq(), 14);
639
640     // second row
641     vr.pageDown();
642     assertEquals(vr.getStartRes(), 40);
643     assertEquals(vr.getEndRes(), 79);
644     assertEquals(vr.getStartSeq(), 0);
645     assertEquals(vr.getEndSeq(), 14);
646
647     // third and last row
648     // note endRes is nominal (>width) to preserve viewport width
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     // another pageDown should do nothing
656     vr.pageDown();
657     assertEquals(vr.getStartRes(), 80);
658     assertEquals(vr.getEndRes(), 119);
659     assertEquals(vr.getStartSeq(), 0);
660     assertEquals(vr.getEndSeq(), 14);
661
662     // back to second row
663     vr.pageUp();
664     assertEquals(vr.getStartRes(), 40);
665     assertEquals(vr.getEndRes(), 79);
666     assertEquals(vr.getStartSeq(), 0);
667     assertEquals(vr.getEndSeq(), 14);
668
669     // back to first row
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     // another pageUp should do nothing
677     vr.pageUp();
678     assertEquals(vr.getStartRes(), 0);
679     assertEquals(vr.getEndRes(), 39);
680     assertEquals(vr.getStartSeq(), 0);
681     assertEquals(vr.getEndSeq(), 14);
682
683     /*
684      * simulate scroll right a few positions
685      */
686     vr.setStartRes(5);
687     assertEquals(vr.getStartRes(), 5);
688     assertEquals(vr.getEndRes(), 5 + width - 1); // 44
689
690     vr.pageDown(); // 5-44 shifts to 45-84
691     assertEquals(vr.getStartRes(), 45);
692     assertEquals(vr.getEndRes(), 84);
693
694     vr.pageDown(); // 45-84 shifts to 85-124
695     assertEquals(vr.getStartRes(), 85);
696     assertEquals(vr.getEndRes(), 124);
697
698     vr.pageDown(); // no change - at end already
699     assertEquals(vr.getStartRes(), 85);
700     assertEquals(vr.getEndRes(), 124);
701
702     vr.pageUp(); // back we go
703     assertEquals(vr.getStartRes(), 45);
704     assertEquals(vr.getEndRes(), 84);
705
706     vr.pageUp();
707     assertEquals(vr.getStartRes(), 5);
708     assertEquals(vr.getEndRes(), 44);
709
710     vr.pageUp(); // back to the start
711     assertEquals(vr.getStartRes(), 0);
712     assertEquals(vr.getEndRes(), 39);
713   }
714
715   @Test(groups = { "Functional" })
716   public void testSetStartEndResWrapped()
717   {
718     ViewportRanges vr = new ViewportRanges(al);
719     vr.setWrappedMode(true);
720     vr.setStartEndRes(-1, -1);
721     assertEquals(vr.getStartRes(), 0);
722     assertEquals(vr.getEndRes(), 0);
723   
724     vr.setStartEndRes(5, 19);
725     assertEquals(vr.getStartRes(), 5);
726     assertEquals(vr.getEndRes(), 19);
727   
728     // bounds are not constrained to alignment width
729     // when in wrapped mode
730     vr.setStartEndRes(88, 888);
731     assertEquals(vr.getStartRes(), 88);
732     assertEquals(vr.getEndRes(), 888);
733   
734     ViewportRanges vrsmall = new ViewportRanges(smallAl);
735     vrsmall.setWrappedMode(true);
736     vrsmall.setStartEndRes(88, 888);
737     assertEquals(vrsmall.getStartRes(), 88);
738     assertEquals(vrsmall.getEndRes(), 888);
739   
740     // make visible alignment width = 0
741     smallAl.getHiddenColumns().hideColumns(0, 6);
742     vrsmall.setStartEndRes(0, 4);
743     assertEquals(vrsmall.getStartRes(), 0);
744     assertEquals(vrsmall.getEndRes(), 4);
745   }
746
747   @Test(groups = { "Functional" })
748   public void testSetViewportStartAndWidthWrapped()
749   {
750     ViewportRanges vr = new ViewportRanges(al);
751     vr.setWrappedMode(true);
752     vr.setViewportStartAndWidth(2, 6);
753     assertEquals(vr.getViewportWidth(), 6);
754     assertEquals(vr.getStartRes(), 2);
755   
756     // reset -ve values of start to 0
757     vr.setViewportStartAndWidth(-1, 7);
758     assertEquals(vr.getViewportWidth(), 7);
759     assertEquals(vr.getStartRes(), 0);
760   
761     // out of bounds values are not forced to within bounds
762     vr.setViewportStartAndWidth(35, 5);
763     assertEquals(vr.getViewportWidth(), 5);
764     assertEquals(vr.getStartRes(), 35);
765   
766     // small alignment doesn't get bounds reset
767     ViewportRanges vrsmall = new ViewportRanges(smallAl);
768     vrsmall.setViewportStartAndWidth(0, 63);
769     assertEquals(vrsmall.getViewportWidth(), 7);
770     assertEquals(vrsmall.getStartRes(), 0);
771   }
772
773   @Test(groups = { "Functional" })
774   public void testGetWrappedMaxScroll()
775   {
776     // generate an ungapped alignment of width 140
777     int alignmentWidth = 140;
778     AlignmentI al2 = gen.generate(alignmentWidth, 15, 1, 0, 5);
779     ViewportRanges vr = new ViewportRanges(al2);
780     vr.setStartEndRes(0, 39);
781     int width = vr.getViewportWidth(); // 40
782     int partWidth = alignmentWidth % width; // 20
783   
784     /*
785      * there are 3 * 40 remainder 20 residues
786      * number of widths depends on offset (scroll right)
787      * 4 widths (maxScroll = 3) if offset by 0 or more than 19 columns
788      * 5 widths (maxScroll = 4) if 1 <= offset <= 19
789      */
790     for (int col = 0; col < alignmentWidth; col++)
791     {
792       int offset = col % width;
793       if (offset > 0 && offset < partWidth)
794       {
795         assertEquals(vr.getWrappedMaxScroll(col), 4, "col " + col);
796       }
797       else
798       {
799         assertEquals(vr.getWrappedMaxScroll(col), 3, "col " + col);
800       }
801     }
802   }
803
804   @Test(groups = { "Functional" })
805   public void testScrollUp_wrapped()
806   {
807     /*
808      * alignment 30 tall and 45 wide
809      */
810     AlignmentI al2 = gen.generate(45, 30, 1, 0, 5);
811
812     /*
813      * wrapped view, 5 sequences high, start at sequence offset 1
814      */
815     ViewportRanges vr = new ViewportRanges(al2);
816     vr.setWrappedMode(true);
817     vr.setViewportStartAndHeight(1, 5);
818
819     /*
820      * offset wrapped view to column 3
821      */
822     vr.setStartEndRes(3, 22);
823
824     int startRes = vr.getStartRes();
825     int width = vr.getViewportWidth();
826     assertEquals(startRes, 3);
827     assertEquals(width, 20);
828
829     // in wrapped mode, we change startRes but not startSeq
830     // scroll down:
831     vr.scrollUp(false);
832     assertEquals(vr.getStartSeq(), 1);
833     assertEquals(vr.getStartRes(), 23);
834
835     // scroll up returns to original position
836     vr.scrollUp(true);
837     assertEquals(vr.getStartSeq(), 1);
838     assertEquals(vr.getStartRes(), 3);
839
840     // scroll up again returns to 'origin'
841     vr.scrollUp(true);
842     assertEquals(vr.getStartSeq(), 1);
843     assertEquals(vr.getStartRes(), 0);
844
845     /*
846      * offset 3 columns once more and do some scroll downs
847      */
848     vr.setStartEndRes(3, 22);
849     vr.scrollUp(false);
850     assertEquals(vr.getStartSeq(), 1);
851     assertEquals(vr.getStartRes(), 23);
852     vr.scrollUp(false);
853     assertEquals(vr.getStartSeq(), 1);
854     assertEquals(vr.getStartRes(), 43);
855
856     /*
857      * scroll down beyond end of alignment does nothing
858      */
859     vr.scrollUp(false);
860     assertEquals(vr.getStartSeq(), 1);
861     assertEquals(vr.getStartRes(), 43);
862   }
863
864   @Test(groups = { "Functional" })
865   public void testSetViewportLocation()
866   {
867     AlignmentI al2 = gen.generate(60, 80, 1, 0, 0);
868
869     ViewportRanges vr = new ViewportRanges(al2);
870
871     // start with viewport on 5-14
872     vr.setViewportStartAndWidth(5, 10);
873     assertEquals(vr.getStartRes(), 5);
874     assertEquals(vr.getEndRes(), 14);
875
876     vr.setViewportStartAndHeight(3, 13);
877     assertEquals(vr.getStartSeq(), 3);
878     assertEquals(vr.getEndSeq(), 15);
879
880     // set location to (8,5) - no change
881     vr.setViewportLocation(8, 5);
882     assertEquals(vr.getStartRes(), 5);
883     assertEquals(vr.getEndRes(), 14);
884     assertEquals(vr.getStartSeq(), 3);
885     assertEquals(vr.getEndSeq(), 15);
886
887     // set location to (40,50) - change to top left (40,50)
888     vr.setViewportLocation(40, 50);
889     assertEquals(vr.getStartRes(), 40);
890     assertEquals(vr.getEndRes(), 49);
891     assertEquals(vr.getStartSeq(), 50);
892     assertEquals(vr.getEndSeq(), 62);
893
894     // set location past end of alignment - resets to leftmost pos
895     vr.setViewportLocation(63, 85);
896     assertEquals(vr.getStartRes(), 50);
897     assertEquals(vr.getEndRes(), 59);
898     assertEquals(vr.getStartSeq(), 67);
899     assertEquals(vr.getEndSeq(), 79);
900
901     // hide some columns
902     al2.getHiddenColumns().hideColumns(20, 50);
903     vr.setViewportLocation(55, 4);
904     assertEquals(vr.getStartRes(), 19);
905     assertEquals(vr.getEndRes(), 28);
906     assertEquals(vr.getStartSeq(), 4);
907     assertEquals(vr.getEndSeq(), 16);
908
909     // hide some sequences
910     al2.getHiddenSequences().hideSequence(al2.getSequenceAt(3));
911     al2.getHiddenSequences().hideSequence(al2.getSequenceAt(4));
912     vr.setViewportLocation(17, 5);
913     assertEquals(vr.getStartRes(), 17);
914     assertEquals(vr.getEndRes(), 26);
915     assertEquals(vr.getStartSeq(), 3);
916     assertEquals(vr.getEndSeq(), 15);
917
918     // set wrapped mode
919     vr.setWrappedMode(true);
920     vr.setViewportLocation(1, 8);
921     assertEquals(vr.getStartRes(), 0);
922     assertEquals(vr.getEndRes(), 9);
923     assertEquals(vr.getStartSeq(), 3);
924     assertEquals(vr.getEndSeq(), 15);
925
926     // try further down the alignment
927     vr.setViewportLocation(57, 5);
928     assertEquals(vr.getStartRes(), 20);
929     assertEquals(vr.getEndRes(), 29);
930     assertEquals(vr.getStartSeq(), 3);
931     assertEquals(vr.getEndSeq(), 15);
932   }
933 }
934
935 // mock listener for property change events
936 class MockPropChangeListener implements ViewportListenerI
937 {
938   private int firecount = 0;
939
940   private List<String> events = new ArrayList<>();
941
942   private List<Integer> newvalues = new ArrayList<>();
943
944   public MockPropChangeListener(ViewportRanges vr)
945   {
946     vr.addPropertyChangeListener(this);
947   }
948
949   @Override
950   public void propertyChange(PropertyChangeEvent evt)
951   {
952     firecount++;
953     events.add(evt.getPropertyName());
954     if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
955     {
956       newvalues.add(((int[]) evt.getNewValue())[0]);
957       newvalues.add(((int[]) evt.getNewValue())[1]);
958     }
959     else
960     {
961       newvalues.add((Integer) evt.getNewValue());
962     }
963   }
964
965   public boolean verify(int count, List<String> eventslist,
966           List<Integer> valueslist)
967   {
968     return (count == firecount) && events.equals(eventslist)
969             && newvalues.equals(valueslist);
970   }
971
972   public boolean verify(int count, List<String> eventslist)
973   {
974     return (count == firecount) && events.equals(eventslist);
975   }
976
977   public void reset()
978   {
979     firecount = 0;
980     events.clear();
981     newvalues.clear();
982   }
983 }