JAL-1858 scrollToWrappedVisible preserve any horizontal offset of view
[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.List;
17
18 import org.testng.annotations.BeforeMethod;
19 import org.testng.annotations.Test;
20
21 public class ViewportRangesTest {
22
23   AlignmentGenerator gen = new AlignmentGenerator(false);
24
25   AlignmentI al = gen.generate(20, 30, 1, 5, 5);
26
27   AlignmentI smallAl = gen.generate(7, 2, 2, 5, 5);
28
29   @BeforeMethod(alwaysRun = true)
30   public void cleanUp()
31   {
32     ColumnSelection sel = new ColumnSelection();
33     al.getHiddenColumns().revealAllHiddenColumns(sel);
34     al.getHiddenSequences().showAll(null);
35     smallAl.getHiddenColumns().revealAllHiddenColumns(sel);
36     smallAl.getHiddenSequences().showAll(null);
37   }
38
39   @Test(groups = { "Functional" })
40   public void testViewportRanges() 
41   {
42     ViewportRanges vr = new ViewportRanges(al);
43     
44     assertEquals(vr.getStartRes(),0);
45     assertEquals(vr.getEndRes(), al.getWidth()-1);
46     assertEquals(vr.getStartSeq(), 0);
47     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
48   }
49
50   @Test(groups = { "Functional" })
51   public void testGetAbsoluteAlignmentHeight()
52   {
53     ViewportRanges vr = new ViewportRanges(al);
54
55     assertEquals(vr.getAbsoluteAlignmentHeight(), al.getHeight());
56
57     al.getHiddenSequences().hideSequence(al.getSequenceAt(3));
58     assertEquals(vr.getAbsoluteAlignmentHeight(), al.getHeight() + 1);
59   }
60
61   @Test(groups = { "Functional" })
62   public void testGetAbsoluteAlignmentWidth()
63   {
64     ViewportRanges vr = new ViewportRanges(al);
65     assertEquals(vr.getAbsoluteAlignmentWidth(), al.getWidth());
66   }
67
68   @Test(groups = { "Functional" })
69   public void testSetEndRes()
70   {
71     ViewportRanges vr = new ViewportRanges(al);
72     vr.setEndRes(-1);
73     assertEquals(vr.getEndRes(), 0);
74
75     vr.setEndRes(al.getWidth() - 1);
76     assertEquals(vr.getEndRes(), al.getWidth() - 1);
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.setEndRes(al.getHeight() - 1);
90     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
91   }
92
93   @Test(groups = { "Functional" })
94   public void testSetStartRes()
95   {
96     ViewportRanges vr = new ViewportRanges(al);
97     vr.setStartRes(-1);
98     assertEquals(vr.getStartRes(), 0);
99
100     vr.setStartRes(al.getWidth());
101     assertEquals(vr.getStartRes(), al.getWidth() - 1);
102
103     vr.setStartRes(al.getWidth() - 1);
104     assertEquals(vr.getStartRes(), al.getWidth() - 1);
105   }
106
107   @Test(groups = { "Functional" })
108   public void testSetStartSeq()
109   {
110     ViewportRanges vr = new ViewportRanges(al);
111     vr.setStartSeq(-1);
112     assertEquals(vr.getStartSeq(), 0);
113
114     vr.setStartSeq(al.getHeight() - vr.getViewportHeight() + 1);
115     assertEquals(vr.getStartSeq(), al.getHeight() - vr.getViewportHeight());
116
117     vr.setStartSeq(al.getHeight() - vr.getViewportHeight());
118     assertEquals(vr.getStartSeq(), al.getHeight() - vr.getViewportHeight());
119   }
120
121   @Test(groups = { "Functional" })
122   public void testSetStartEndRes()
123   {
124     ViewportRanges vr = new ViewportRanges(al);
125     vr.setStartEndRes(-1, -1);
126     assertEquals(vr.getStartRes(), 0);
127     assertEquals(vr.getEndRes(), 0);
128
129     vr.setStartEndRes(5, 19);
130     assertEquals(vr.getStartRes(), 5);
131     assertEquals(vr.getEndRes(), 19);
132
133     vr.setStartEndRes(al.getWidth(), al.getWidth());
134     assertEquals(vr.getEndRes(), al.getWidth() - 1);
135
136     ViewportRanges vrsmall = new ViewportRanges(smallAl);
137     vrsmall.setStartEndRes(al.getWidth(), al.getWidth());
138     assertEquals(vrsmall.getEndRes(), 6);
139
140     // make visible alignment width = 0
141     smallAl.getHiddenColumns().hideColumns(0, 6);
142     vrsmall.setStartEndRes(0, 4);
143     assertEquals(vrsmall.getStartRes(), 0);
144     assertEquals(vrsmall.getEndRes(), 0);
145   }
146
147   @Test(groups = { "Functional" })
148   public void testSetStartEndSeq()
149   {
150     ViewportRanges vr = new ViewportRanges(al);
151     vr.setStartEndSeq(-1, -1);
152     assertEquals(vr.getStartSeq(), 0);
153     assertEquals(vr.getEndSeq(), 0);
154
155     vr.setStartEndSeq(5, 19);
156     assertEquals(vr.getStartSeq(), 5);
157     assertEquals(vr.getEndSeq(), 19);
158
159     vr.setStartEndSeq(al.getHeight(), al.getHeight());
160     assertEquals(vr.getEndSeq(), al.getHeight() - 1);
161
162     // make visible alignment height = 0
163     smallAl.getHiddenSequences().hideSequence(smallAl.getSequenceAt(0));
164     smallAl.getHiddenSequences().hideSequence(smallAl.getSequenceAt(0));
165     ViewportRanges vrsmall = new ViewportRanges(smallAl);
166     vrsmall.setStartEndSeq(0, 3);
167     assertEquals(vrsmall.getStartSeq(), 0);
168     assertEquals(vrsmall.getEndSeq(), 0);
169   }
170
171   @Test(groups = { "Functional" })
172   public void testSetViewportHeight()
173   {
174     ViewportRanges vr = new ViewportRanges(al);
175     vr.setViewportHeight(13);
176     assertEquals(vr.getViewportHeight(), 13);
177   }
178
179   @Test(groups = { "Functional" })
180   public void testSetViewportWidth()
181   {
182     ViewportRanges vr = new ViewportRanges(al);
183     vr.setViewportWidth(13);
184     assertEquals(vr.getViewportWidth(), 13);
185   }
186
187   @Test(groups = { "Functional" })
188   public void testSetViewportStartAndHeight()
189   {
190     ViewportRanges vr = new ViewportRanges(al);
191     vr.setViewportStartAndHeight(2, 6);
192     assertEquals(vr.getViewportHeight(), 6);
193     assertEquals(vr.getStartSeq(), 2);
194
195     // reset -ve values of start to 0
196     vr.setViewportStartAndHeight(-1, 7);
197     assertEquals(vr.getViewportHeight(), 7);
198     assertEquals(vr.getStartSeq(), 0);
199
200     // reset out of bounds start values to within bounds
201     vr.setViewportStartAndHeight(35, 5);
202     assertEquals(vr.getViewportHeight(), 5);
203     assertEquals(vr.getStartSeq(), 24);
204   }
205
206   @Test(groups = { "Functional" })
207   public void testSetViewportStartAndWidth()
208   {
209     ViewportRanges vr = new ViewportRanges(al);
210     vr.setViewportStartAndWidth(2, 6);
211     assertEquals(vr.getViewportWidth(), 6);
212     assertEquals(vr.getStartRes(), 2);
213
214     // reset -ve values of start to 0
215     vr.setViewportStartAndWidth(-1, 7);
216     assertEquals(vr.getViewportWidth(), 7);
217     assertEquals(vr.getStartRes(), 0);
218
219     // reset out of bounds start values to within bounds
220     vr.setViewportStartAndWidth(35, 5);
221     assertEquals(vr.getViewportWidth(), 5);
222     assertEquals(vr.getStartRes(), 16);
223
224     // small alignment doesn't get bounds reset
225     ViewportRanges vrsmall = new ViewportRanges(smallAl);
226     vrsmall.setViewportStartAndWidth(0, 63);
227     assertEquals(vrsmall.getViewportWidth(), 7);
228     assertEquals(vrsmall.getStartRes(), 0);
229   }
230
231   @Test(groups = { "Functional" })
232   public void testPageUpDown()
233   {
234     ViewportRanges vr = new ViewportRanges(al);
235     vr.setViewportStartAndHeight(8, 6);
236     vr.pageDown();
237     assertEquals(vr.getStartSeq(), 13);
238
239     vr.pageUp();
240     assertEquals(vr.getStartSeq(), 8);
241
242     vr.pageUp();
243     assertEquals(vr.getStartSeq(), 3);
244
245     vr.pageUp();
246     // pageup does not go beyond 0, viewport height stays the same
247     assertEquals(vr.getStartSeq(), 0);
248     assertEquals(vr.getViewportHeight(), 6);
249
250     vr.pageDown();
251     vr.pageDown();
252     vr.pageDown();
253     vr.pageDown();
254     vr.pageDown();
255
256     // pagedown to bottom does not go beyond end, and height stays same
257     assertEquals(vr.getStartSeq(), 24);
258     assertEquals(vr.getViewportHeight(), 6);
259   }
260
261   @Test(groups = { "Functional" })
262   public void testScrollUp()
263   {
264     ViewportRanges vr = new ViewportRanges(al);
265     vr.setViewportStartAndHeight(1, 5);
266     vr.scrollUp(true);
267     assertEquals(vr.getStartSeq(), 0);
268     // can't scroll above top
269     vr.scrollUp(true);
270     assertEquals(vr.getStartSeq(), 0);
271
272     vr.setViewportStartAndHeight(24, 5);
273     vr.scrollUp(false);
274     assertEquals(vr.getStartSeq(), 25);
275     // can't scroll beyond bottom
276     vr.scrollUp(false);
277     assertEquals(vr.getStartSeq(), 25);
278   }
279
280   @Test(groups = { "Functional" })
281   public void testScrollUpWithHidden()
282   {
283     ViewportRanges vr = new ViewportRanges(al);
284
285     // hide last sequence
286     HiddenSequences hidden = new HiddenSequences(al);
287     hidden.hideSequence(al.getSequenceAt(29));
288
289     vr.setViewportStartAndHeight(1, 5);
290     vr.scrollUp(true);
291     assertEquals(vr.getStartSeq(), 0);
292     // can't scroll above top
293     vr.scrollUp(true);
294     assertEquals(vr.getStartSeq(), 0);
295
296     vr.setViewportStartAndHeight(23, 5);
297     vr.scrollUp(false);
298     assertEquals(vr.getStartSeq(), 24);
299     // can't scroll beyond bottom
300     vr.scrollUp(false);
301     assertEquals(vr.getStartSeq(), 24);
302   }
303
304   @Test(groups = { "Functional" })
305   public void testScrollRight()
306   {
307     ViewportRanges vr = new ViewportRanges(al);
308     vr.setViewportStartAndWidth(1, 5);
309     vr.scrollRight(false);
310     assertEquals(vr.getStartRes(), 0);
311     // can't scroll left past start
312     vr.scrollRight(false);
313     assertEquals(vr.getStartRes(), 0);
314
315     vr.setViewportStartAndWidth(15, 5);
316     vr.scrollRight(true);
317     assertEquals(vr.getStartRes(), 16);
318     // can't scroll right past end
319     vr.scrollRight(true);
320     assertEquals(vr.getStartRes(), 16);
321   }
322
323   @Test(groups = { "Functional" })
324   public void testScrollRightWithHidden()
325   {
326     ViewportRanges vr = new ViewportRanges(al);
327
328     // hide last 2 columns
329     HiddenColumns cols = new HiddenColumns();
330     cols.hideColumns(19, 20);
331     al.setHiddenColumns(cols);
332
333     vr.setViewportStartAndWidth(1, 5);
334     vr.scrollRight(false);
335     assertEquals(vr.getStartRes(), 0);
336     // can't scroll left past start
337     vr.scrollRight(false);
338     assertEquals(vr.getStartRes(), 0);
339
340     vr.setViewportStartAndWidth(13, 5);
341     vr.scrollRight(true);
342     assertEquals(vr.getStartRes(), 14);
343     // can't scroll right past last visible col
344     vr.scrollRight(true);
345     assertEquals(vr.getStartRes(), 14);
346   }
347
348   @Test(groups = { "Functional" })
349   public void testScrollToWrappedVisible()
350   {
351     AlignmentI al2 = gen.generate(60, 30, 1, 5, 5);
352
353     ViewportRanges vr = new ViewportRanges(al2);
354
355     // start with viewport on 5-14
356     vr.setViewportStartAndWidth(5, 10);
357     assertEquals(vr.getStartRes(), 5);
358     assertEquals(vr.getEndRes(), 14);
359
360     // scroll to 12 - no change
361     assertFalse(vr.scrollToWrappedVisible(12));
362     assertEquals(vr.getStartRes(), 5);
363
364     // scroll to 2 - back to 0-9
365     assertTrue(vr.scrollToWrappedVisible(2));
366     assertEquals(vr.getStartRes(), 0);
367     assertEquals(vr.getEndRes(), 9);
368
369     // scroll to 9 - no change
370     assertFalse(vr.scrollToWrappedVisible(9));
371     assertEquals(vr.getStartRes(), 0);
372
373     // scroll to 12 - moves to 10-19
374     assertTrue(vr.scrollToWrappedVisible(12));
375     assertEquals(vr.getStartRes(), 10);
376     assertEquals(vr.getEndRes(), 19);
377
378     vr.setStartRes(13);
379     assertEquals(vr.getStartRes(), 13);
380     assertEquals(vr.getEndRes(), 22);
381
382     // scroll to 45 - jumps to 43-52
383     assertTrue(vr.scrollToWrappedVisible(45));
384     assertEquals(vr.getStartRes(), 43);
385     assertEquals(vr.getEndRes(), 52);
386   }
387
388   // leave until JAL-2388 is merged and we can do without viewport
389   /*@Test(groups = { "Functional" })
390   public void testScrollToVisible()
391   {
392     ViewportRanges vr = new ViewportRanges(al);
393     vr.setViewportStartAndWidth(12,5);
394     vr.setViewportStartAndHeight(10,6);
395     vr.scrollToVisible(13,14)
396     
397     // no change
398     assertEquals(vr.getStartRes(), 12);
399     assertEquals(vr.getStartSeq(), 10);
400     
401     vr.scrollToVisible(5,6);
402     assertEquals(vr.getStartRes(), 5);
403     assertEquals(vr.getStartSeq(), 6);
404     
405     // test for hidden columns too
406   }*/
407
408   @Test(groups = { "Functional" })
409   public void testEventFiring()
410   {
411     ViewportRanges vr = new ViewportRanges(al);
412     MockPropChangeListener l = new MockPropChangeListener(vr);
413     List<String> emptylist = new ArrayList<>();
414
415     vr.setViewportWidth(5);
416     vr.setViewportHeight(5);
417     l.reset();
418
419     // one event fired when startRes is called with new value
420     vr.setStartRes(4);
421     assertTrue(l.verify(1, Arrays.asList("startres")));
422     l.reset();
423
424     // no event fired for same value
425     vr.setStartRes(4);
426     assertTrue(l.verify(0, emptylist));
427     l.reset();
428
429     vr.setEndRes(10);
430     assertTrue(l.verify(1, Arrays.asList("startres")));
431     l.reset();
432
433     // no event fired for same value
434     vr.setEndRes(10);
435     assertTrue(l.verify(0, emptylist));
436     l.reset();
437
438     vr.setStartSeq(4);
439     assertTrue(l.verify(1, Arrays.asList("startseq")));
440     l.reset();
441
442     vr.setStartSeq(4);
443     assertTrue(l.verify(0, emptylist));
444     l.reset();
445
446     vr.setEndSeq(10);
447     assertTrue(l.verify(1, Arrays.asList("startseq")));
448     l.reset();
449
450     vr.setEndSeq(10);
451     assertTrue(l.verify(0, emptylist));
452     l.reset();
453
454     vr.setStartEndRes(2, 15);
455     assertTrue(l.verify(1, Arrays.asList("startres")));
456     l.reset();
457
458     vr.setStartEndRes(2, 15);
459     assertTrue(l.verify(0, emptylist));
460     l.reset();
461
462     // check new value fired by event is corrected startres
463     vr.setStartEndRes(-1, 5);
464     assertTrue(l.verify(1, Arrays.asList("startres"), Arrays.asList(0)));
465     l.reset();
466
467     // check new value fired by event is corrected endres
468     vr.setStartEndRes(0, -1);
469     assertTrue(l.verify(1, Arrays.asList("endres"), Arrays.asList(0)));
470     l.reset();
471
472     vr.setStartEndSeq(2, 15);
473     assertTrue(l.verify(1, Arrays.asList("startseq")));
474     l.reset();
475
476     vr.setStartEndSeq(2, 15);
477     assertTrue(l.verify(0, emptylist));
478     l.reset();
479
480     vr.setStartEndRes(2, 2); // so seq and res values should be different, in
481                              // case of transposing in code
482     l.reset();
483
484     // check new value fired by event is corrected startseq
485     vr.setStartEndSeq(-1, 5);
486     assertTrue(l.verify(1, Arrays.asList("startseq"), Arrays.asList(0)));
487     l.reset();
488
489     // check new value fired by event is corrected endseq
490     vr.setStartEndSeq(0, -1);
491     assertTrue(l.verify(1, Arrays.asList("endseq"), Arrays.asList(0)));
492     l.reset();
493
494     // reset for later tests
495     vr.setStartEndSeq(2, 15);
496     l.reset();
497
498     // test viewport height and width setting triggers event
499     vr.setViewportHeight(10);
500     assertTrue(l.verify(1, Arrays.asList("endseq")));
501     l.reset();
502
503     vr.setViewportWidth(18);
504     assertTrue(l.verify(1, Arrays.asList("endres")));
505     l.reset();
506
507     // already has seq start set to 2, so triggers endseq
508     vr.setViewportStartAndHeight(2, 16);
509     assertTrue(l.verify(1, Arrays.asList("endseq")));
510     l.reset();
511
512     vr.setViewportStartAndWidth(1, 14);
513     assertTrue(l.verify(1, Arrays.asList("startres")));
514     l.reset();
515
516     // test page up/down triggers event
517     vr.pageUp();
518     assertTrue(l.verify(1, Arrays.asList("startseq")));
519     l.reset();
520
521     vr.pageDown();
522     assertTrue(l.verify(1, Arrays.asList("startseq")));
523     l.reset();
524
525     // test scrolling triggers event
526     vr.scrollUp(true);
527     assertTrue(l.verify(1, Arrays.asList("startseq")));
528     l.reset();
529
530     vr.scrollUp(false);
531     assertTrue(l.verify(1, Arrays.asList("startseq")));
532     l.reset();
533
534     vr.scrollRight(true);
535     assertTrue(l.verify(1, Arrays.asList("startres")));
536     l.reset();
537
538     vr.scrollRight(false);
539     assertTrue(l.verify(1, Arrays.asList("startres")));
540     l.reset();
541
542     vr.scrollToVisible(10, 10);
543     assertTrue(l.verify(4,
544             Arrays.asList("startseq", "startseq", "startseq", "startseq")));
545     l.reset();
546
547     vr.scrollToWrappedVisible(5);
548     assertTrue(l.verify(1, Arrays.asList("startres")));
549     l.reset();
550   }
551 }
552
553 // mock listener for property change events
554 class MockPropChangeListener implements ViewportListenerI
555 {
556   private int firecount = 0;
557
558   private List<String> events = new ArrayList<>();
559
560   private List<Integer> newvalues = new ArrayList<>();
561
562   public MockPropChangeListener(ViewportRanges vr)
563   {
564     vr.addPropertyChangeListener(this);
565   }
566
567   @Override
568   public void propertyChange(PropertyChangeEvent evt)
569   {
570     firecount++;
571     events.add(evt.getPropertyName());
572     newvalues.add((Integer) evt.getNewValue());
573   }
574
575   public boolean verify(int count, List<String> eventslist,
576           List<Integer> valueslist)
577   {
578     return (count == firecount) && events.equals(eventslist)
579             && newvalues.equals(valueslist);
580   }
581
582   public boolean verify(int count, List<String> eventslist)
583   {
584     return (count == firecount) && events.equals(eventslist);
585   }
586
587   public void reset()
588   {
589     firecount = 0;
590     events.clear();
591     newvalues.clear();
592   }
593 }