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