package jalview.viewmodel; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import jalview.analysis.AlignmentGenerator; import jalview.datamodel.AlignmentI; import jalview.datamodel.ColumnSelection; import jalview.datamodel.HiddenColumns; import jalview.datamodel.HiddenSequences; import java.beans.PropertyChangeEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class ViewportRangesTest { AlignmentGenerator gen = new AlignmentGenerator(false); AlignmentI al = gen.generate(20, 30, 1, 5, 5); AlignmentI smallAl = gen.generate(7, 2, 2, 5, 5); @BeforeClass(alwaysRun = true) public void setUp() { gen = new AlignmentGenerator(false); al = gen.generate(20, 30, 1, 5, 5); smallAl = gen.generate(7, 2, 2, 5, 5); } @BeforeMethod(alwaysRun = true) public void cleanUp() { ColumnSelection sel = new ColumnSelection(); al.getHiddenColumns().revealAllHiddenColumns(sel); al.getHiddenSequences().showAll(null); smallAl.getHiddenColumns().revealAllHiddenColumns(sel); smallAl.getHiddenSequences().showAll(null); } @Test(groups = { "Functional" }) public void testViewportRanges() { ViewportRanges vr = new ViewportRanges(al); assertEquals(vr.getStartRes(),0); assertEquals(vr.getEndRes(), al.getWidth()-1); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), al.getHeight() - 1); } @Test(groups = { "Functional" }) public void testGetAbsoluteAlignmentHeight() { ViewportRanges vr = new ViewportRanges(al); assertEquals(vr.getAbsoluteAlignmentHeight(), al.getHeight()); al.getHiddenSequences().hideSequence(al.getSequenceAt(3)); assertEquals(vr.getAbsoluteAlignmentHeight(), al.getHeight() + 1); } @Test(groups = { "Functional" }) public void testGetAbsoluteAlignmentWidth() { ViewportRanges vr = new ViewportRanges(al); assertEquals(vr.getAbsoluteAlignmentWidth(), al.getWidth()); } @Test(groups = { "Functional" }) public void testSetEndSeq() { ViewportRanges vr = new ViewportRanges(al); vr.setEndSeq(-1); assertEquals(vr.getEndSeq(), 0); vr.setEndSeq(al.getHeight()); assertEquals(vr.getEndSeq(), al.getHeight() - 1); // vr.setEndRes(al.getHeight() - 1); vr.setEndSeq(al.getHeight() - 1); assertEquals(vr.getEndSeq(), al.getHeight() - 1); } @Test(groups = { "Functional" }) public void testSetStartRes() { ViewportRanges vr = new ViewportRanges(al); vr.setStartRes(-1); assertEquals(vr.getStartRes(), 0); vr.setStartRes(al.getWidth()); assertEquals(vr.getStartRes(), al.getWidth() - 1); vr.setStartRes(al.getWidth() - 1); assertEquals(vr.getStartRes(), al.getWidth() - 1); } @Test(groups = { "Functional" }) public void testSetStartSeq() { ViewportRanges vr = new ViewportRanges(al); vr.setStartSeq(-1); assertEquals(vr.getStartSeq(), 0); vr.setStartSeq(al.getHeight() - vr.getViewportHeight() + 1); assertEquals(vr.getStartSeq(), al.getHeight() - vr.getViewportHeight()); vr.setStartSeq(al.getHeight() - vr.getViewportHeight()); assertEquals(vr.getStartSeq(), al.getHeight() - vr.getViewportHeight()); } @Test(groups = { "Functional" }) public void testSetStartEndRes() { ViewportRanges vr = new ViewportRanges(al); vr.setStartEndRes(-1, -1); assertEquals(vr.getStartRes(), 0); assertEquals(vr.getEndRes(), 0); vr.setStartEndRes(5, 19); assertEquals(vr.getStartRes(), 5); assertEquals(vr.getEndRes(), 19); vr.setStartEndRes(al.getWidth(), al.getWidth()); assertEquals(vr.getEndRes(), al.getWidth() - 1); ViewportRanges vrsmall = new ViewportRanges(smallAl); vrsmall.setStartEndRes(al.getWidth(), al.getWidth()); assertEquals(vrsmall.getEndRes(), 6); // make visible alignment width = 0 smallAl.getHiddenColumns().hideColumns(0, 6); vrsmall.setStartEndRes(0, 4); assertEquals(vrsmall.getStartRes(), 0); assertEquals(vrsmall.getEndRes(), 0); } @Test(groups = { "Functional" }) public void testSetStartEndSeq() { ViewportRanges vr = new ViewportRanges(al); vr.setStartEndSeq(-1, -1); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), 0); vr.setStartEndSeq(5, 19); assertEquals(vr.getStartSeq(), 5); assertEquals(vr.getEndSeq(), 19); vr.setStartEndSeq(al.getHeight(), al.getHeight()); assertEquals(vr.getEndSeq(), al.getHeight() - 1); // make visible alignment height = 0 smallAl.getHiddenSequences().hideSequence(smallAl.getSequenceAt(0)); smallAl.getHiddenSequences().hideSequence(smallAl.getSequenceAt(0)); ViewportRanges vrsmall = new ViewportRanges(smallAl); vrsmall.setStartEndSeq(0, 3); assertEquals(vrsmall.getStartSeq(), 0); assertEquals(vrsmall.getEndSeq(), 0); } @Test(groups = { "Functional" }) public void testSetViewportHeight() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportHeight(13); assertEquals(vr.getViewportHeight(), 13); } @Test(groups = { "Functional" }) public void testSetViewportWidth() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportWidth(13); assertEquals(vr.getViewportWidth(), 13); } @Test(groups = { "Functional" }) public void testSetViewportStartAndHeight() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportStartAndHeight(2, 6); assertEquals(vr.getViewportHeight(), 6); assertEquals(vr.getStartSeq(), 2); // reset -ve values of start to 0 vr.setViewportStartAndHeight(-1, 7); assertEquals(vr.getViewportHeight(), 7); assertEquals(vr.getStartSeq(), 0); // reset out of bounds start values to within bounds vr.setViewportStartAndHeight(35, 5); assertEquals(vr.getViewportHeight(), 5); assertEquals(vr.getStartSeq(), 24); } @Test(groups = { "Functional" }) public void testSetViewportStartAndWidth() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportStartAndWidth(2, 6); assertEquals(vr.getViewportWidth(), 6); assertEquals(vr.getStartRes(), 2); // reset -ve values of start to 0 vr.setViewportStartAndWidth(-1, 7); assertEquals(vr.getViewportWidth(), 7); assertEquals(vr.getStartRes(), 0); // reset out of bounds start values to within bounds vr.setViewportStartAndWidth(35, 5); assertEquals(vr.getViewportWidth(), 5); assertEquals(vr.getStartRes(), 16); // small alignment doesn't get bounds reset ViewportRanges vrsmall = new ViewportRanges(smallAl); vrsmall.setViewportStartAndWidth(0, 63); assertEquals(vrsmall.getViewportWidth(), 7); assertEquals(vrsmall.getStartRes(), 0); } @Test(groups = { "Functional" }) public void testPageUpDown() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportStartAndHeight(8, 6); vr.pageDown(); assertEquals(vr.getStartSeq(), 13); vr.pageUp(); assertEquals(vr.getStartSeq(), 8); vr.pageUp(); assertEquals(vr.getStartSeq(), 3); vr.pageUp(); // pageup does not go beyond 0, viewport height stays the same assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getViewportHeight(), 6); vr.pageDown(); vr.pageDown(); vr.pageDown(); vr.pageDown(); vr.pageDown(); // pagedown to bottom does not go beyond end, and height stays same assertEquals(vr.getStartSeq(), 24); assertEquals(vr.getViewportHeight(), 6); } @Test(groups = { "Functional" }) public void testScrollUp() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportStartAndHeight(1, 5); vr.scrollUp(true); assertEquals(vr.getStartSeq(), 0); // can't scroll above top vr.scrollUp(true); assertEquals(vr.getStartSeq(), 0); vr.setViewportStartAndHeight(24, 5); vr.scrollUp(false); assertEquals(vr.getStartSeq(), 25); // can't scroll beyond bottom vr.scrollUp(false); assertEquals(vr.getStartSeq(), 25); } @Test(groups = { "Functional" }) public void testScrollUpWithHidden() { ViewportRanges vr = new ViewportRanges(al); // hide last sequence HiddenSequences hidden = new HiddenSequences(al); hidden.hideSequence(al.getSequenceAt(29)); vr.setViewportStartAndHeight(1, 5); vr.scrollUp(true); assertEquals(vr.getStartSeq(), 0); // can't scroll above top vr.scrollUp(true); assertEquals(vr.getStartSeq(), 0); vr.setViewportStartAndHeight(23, 5); vr.scrollUp(false); assertEquals(vr.getStartSeq(), 24); // can't scroll beyond bottom vr.scrollUp(false); assertEquals(vr.getStartSeq(), 24); } @Test(groups = { "Functional" }) public void testScrollRight() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportStartAndWidth(1, 5); vr.scrollRight(false); assertEquals(vr.getStartRes(), 0); // can't scroll left past start vr.scrollRight(false); assertEquals(vr.getStartRes(), 0); vr.setViewportStartAndWidth(15, 5); vr.scrollRight(true); assertEquals(vr.getStartRes(), 16); // can't scroll right past end vr.scrollRight(true); assertEquals(vr.getStartRes(), 16); } @Test(groups = { "Functional" }) public void testScrollRightWithHidden() { ViewportRanges vr = new ViewportRanges(al); // hide last 2 columns HiddenColumns cols = new HiddenColumns(); cols.hideColumns(19, 20); al.setHiddenColumns(cols); vr.setViewportStartAndWidth(1, 5); vr.scrollRight(false); assertEquals(vr.getStartRes(), 0); // can't scroll left past start vr.scrollRight(false); assertEquals(vr.getStartRes(), 0); vr.setViewportStartAndWidth(13, 5); vr.scrollRight(true); assertEquals(vr.getStartRes(), 14); // can't scroll right past last visible col vr.scrollRight(true); assertEquals(vr.getStartRes(), 14); } @Test(groups = { "Functional" }) public void testScrollToWrappedVisible() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportStartAndWidth(5, 10); vr.scrollToWrappedVisible(0); assertEquals(vr.getStartRes(), 0); vr.scrollToWrappedVisible(10); assertEquals(vr.getStartRes(), 10); vr.scrollToWrappedVisible(15); assertEquals(vr.getStartRes(), 10); } // leave until JAL-2388 is merged and we can do without viewport /*@Test(groups = { "Functional" }) public void testScrollToVisible() { ViewportRanges vr = new ViewportRanges(al); vr.setViewportStartAndWidth(12,5); vr.setViewportStartAndHeight(10,6); vr.scrollToVisible(13,14) // no change assertEquals(vr.getStartRes(), 12); assertEquals(vr.getStartSeq(), 10); vr.scrollToVisible(5,6); assertEquals(vr.getStartRes(), 5); assertEquals(vr.getStartSeq(), 6); // test for hidden columns too }*/ @Test(groups = { "Functional" }) public void testEventFiring() { ViewportRanges vr = new ViewportRanges(al); MockPropChangeListener l = new MockPropChangeListener(vr); List emptylist = new ArrayList<>(); vr.setViewportWidth(5); vr.setViewportHeight(5); l.reset(); // one event fired when startRes is called with new value vr.setStartRes(4); assertTrue(l.verify(1, Arrays.asList("startres"))); l.reset(); // no event fired for same value vr.setStartRes(4); assertTrue(l.verify(0, emptylist)); l.reset(); vr.setStartSeq(4); assertTrue(l.verify(1, Arrays.asList("startseq"))); l.reset(); vr.setStartSeq(4); assertTrue(l.verify(0, emptylist)); l.reset(); vr.setEndSeq(10); assertTrue(l.verify(1, Arrays.asList("startseq"))); l.reset(); vr.setEndSeq(10); assertTrue(l.verify(0, emptylist)); l.reset(); vr.setStartEndRes(2, 15); assertTrue(l.verify(1, Arrays.asList("startres"))); l.reset(); vr.setStartEndRes(2, 15); assertTrue(l.verify(0, emptylist)); l.reset(); // check new value fired by event is corrected startres vr.setStartEndRes(-1, 5); assertTrue(l.verify(1, Arrays.asList("startres"), Arrays.asList(0))); l.reset(); // check new value fired by event is corrected endres vr.setStartEndRes(0, -1); assertTrue(l.verify(1, Arrays.asList("endres"), Arrays.asList(0))); l.reset(); vr.setStartEndSeq(2, 15); assertTrue(l.verify(1, Arrays.asList("startseq"))); l.reset(); vr.setStartEndSeq(2, 15); assertTrue(l.verify(0, emptylist)); l.reset(); vr.setStartEndRes(2, 2); // so seq and res values should be different, in // case of transposing in code l.reset(); // check new value fired by event is corrected startseq vr.setStartEndSeq(-1, 5); assertTrue(l.verify(1, Arrays.asList("startseq"), Arrays.asList(0))); l.reset(); // check new value fired by event is corrected endseq vr.setStartEndSeq(0, -1); assertTrue(l.verify(1, Arrays.asList("endseq"), Arrays.asList(0))); l.reset(); // reset for later tests vr.setStartEndSeq(2, 15); l.reset(); // test viewport height and width setting triggers event vr.setViewportHeight(10); assertTrue(l.verify(1, Arrays.asList("endseq"))); l.reset(); vr.setViewportWidth(18); assertTrue(l.verify(1, Arrays.asList("endres"))); l.reset(); // already has seq start set to 2, so triggers endseq vr.setViewportStartAndHeight(2, 16); assertTrue(l.verify(1, Arrays.asList("endseq"))); l.reset(); vr.setViewportStartAndWidth(1, 14); assertTrue(l.verify(1, Arrays.asList("startres"))); l.reset(); // test page up/down triggers event vr.pageUp(); assertTrue(l.verify(1, Arrays.asList("startseq"))); l.reset(); vr.pageDown(); assertTrue(l.verify(1, Arrays.asList("startseq"))); l.reset(); // test scrolling triggers event vr.scrollUp(true); assertTrue(l.verify(1, Arrays.asList("startseq"))); l.reset(); vr.scrollUp(false); assertTrue(l.verify(1, Arrays.asList("startseq"))); l.reset(); vr.scrollRight(true); assertTrue(l.verify(1, Arrays.asList("startres"))); l.reset(); vr.scrollRight(false); assertTrue(l.verify(1, Arrays.asList("startres"))); l.reset(); vr.scrollToVisible(10, 10); assertTrue(l.verify(4, Arrays.asList("startseq", "startseq", "startseq", "startseq"))); l.reset(); vr.scrollToWrappedVisible(5); assertTrue(l.verify(1, Arrays.asList("startres"))); l.reset(); } @Test(groups = { "Functional" }) public void testGetWrappedScrollPosition() { AlignmentI al2 = gen.generate(157, 15, 1, 5, 5); ViewportRanges vr = new ViewportRanges(al2); vr.setStartEndRes(0, 39); int width = vr.getViewportWidth(); // 40 /* * scroll is 0 at column 0 (only) */ assertEquals(vr.getWrappedScrollPosition(0), 0); /* * scroll is 1 at columns 1-40 */ int i = 1; int j = width; for (; i <= j; i++) { assertEquals(1, vr.getWrappedScrollPosition(i)); } /* * scroll is 2 at columns 41-80, etc */ j += width; for (; i <= j; i++) { assertEquals(2, vr.getWrappedScrollPosition(i), "For " + i); } } @Test(groups = { "Functional" }) public void testPageUpDownWrapped() { /* * 15 sequences, 110 residues wide (+gaps) */ AlignmentI al2 = gen.generate(110, 15, 1, 5, 5); ViewportRanges vr = new ViewportRanges(al2); vr.setWrappedMode(true); // first row vr.setViewportStartAndWidth(0, 40); int width = vr.getViewportWidth(); assertEquals(width, 40); assertEquals(vr.getStartRes(), 0); assertEquals(vr.getEndRes(), 39); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), 14); // second row vr.pageDown(); assertEquals(vr.getStartRes(), 40); assertEquals(vr.getEndRes(), 79); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), 14); // third and last row // note endRes is nominal (>width) to preserve viewport width vr.pageDown(); assertEquals(vr.getStartRes(), 80); assertEquals(vr.getEndRes(), 119); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), 14); // another pageDown should do nothing vr.pageDown(); assertEquals(vr.getStartRes(), 80); assertEquals(vr.getEndRes(), 119); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), 14); // back to second row vr.pageUp(); assertEquals(vr.getStartRes(), 40); assertEquals(vr.getEndRes(), 79); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), 14); // back to first row vr.pageUp(); assertEquals(vr.getStartRes(), 0); assertEquals(vr.getEndRes(), 39); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), 14); // another pageUp should do nothing vr.pageUp(); assertEquals(vr.getStartRes(), 0); assertEquals(vr.getEndRes(), 39); assertEquals(vr.getStartSeq(), 0); assertEquals(vr.getEndSeq(), 14); /* * simulate scroll right a few positions */ vr.setStartRes(5); assertEquals(vr.getStartRes(), 5); assertEquals(vr.getEndRes(), 5 + width - 1); // 44 vr.pageDown(); // 5-44 shifts to 45-84 assertEquals(vr.getStartRes(), 45); assertEquals(vr.getEndRes(), 84); vr.pageDown(); // 45-84 shifts to 85-124 assertEquals(vr.getStartRes(), 85); assertEquals(vr.getEndRes(), 124); vr.pageDown(); // no change - at end already assertEquals(vr.getStartRes(), 85); assertEquals(vr.getEndRes(), 124); vr.pageUp(); // back we go assertEquals(vr.getStartRes(), 45); assertEquals(vr.getEndRes(), 84); vr.pageUp(); assertEquals(vr.getStartRes(), 5); assertEquals(vr.getEndRes(), 44); vr.pageUp(); // back to the start assertEquals(vr.getStartRes(), 0); assertEquals(vr.getEndRes(), 39); } @Test(groups = { "Functional" }) public void testSetStartEndResWrapped() { ViewportRanges vr = new ViewportRanges(al); vr.setWrappedMode(true); vr.setStartEndRes(-1, -1); assertEquals(vr.getStartRes(), 0); assertEquals(vr.getEndRes(), 0); vr.setStartEndRes(5, 19); assertEquals(vr.getStartRes(), 5); assertEquals(vr.getEndRes(), 19); // bounds are not constrained to alignment width // when in wrapped mode vr.setStartEndRes(88, 888); assertEquals(vr.getStartRes(), 88); assertEquals(vr.getEndRes(), 888); ViewportRanges vrsmall = new ViewportRanges(smallAl); vrsmall.setWrappedMode(true); vrsmall.setStartEndRes(88, 888); assertEquals(vrsmall.getStartRes(), 88); assertEquals(vrsmall.getEndRes(), 888); // make visible alignment width = 0 smallAl.getHiddenColumns().hideColumns(0, 6); vrsmall.setStartEndRes(0, 4); assertEquals(vrsmall.getStartRes(), 0); assertEquals(vrsmall.getEndRes(), 4); } @Test(groups = { "Functional" }) public void testSetViewportStartAndWidthWrapped() { ViewportRanges vr = new ViewportRanges(al); vr.setWrappedMode(true); vr.setViewportStartAndWidth(2, 6); assertEquals(vr.getViewportWidth(), 6); assertEquals(vr.getStartRes(), 2); // reset -ve values of start to 0 vr.setViewportStartAndWidth(-1, 7); assertEquals(vr.getViewportWidth(), 7); assertEquals(vr.getStartRes(), 0); // out of bounds values are not forced to within bounds vr.setViewportStartAndWidth(35, 5); assertEquals(vr.getViewportWidth(), 5); assertEquals(vr.getStartRes(), 35); // small alignment doesn't get bounds reset ViewportRanges vrsmall = new ViewportRanges(smallAl); vrsmall.setViewportStartAndWidth(0, 63); assertEquals(vrsmall.getViewportWidth(), 7); assertEquals(vrsmall.getStartRes(), 0); } } // mock listener for property change events class MockPropChangeListener implements ViewportListenerI { private int firecount = 0; private List events = new ArrayList<>(); private List newvalues = new ArrayList<>(); public MockPropChangeListener(ViewportRanges vr) { vr.addPropertyChangeListener(this); } @Override public void propertyChange(PropertyChangeEvent evt) { firecount++; events.add(evt.getPropertyName()); newvalues.add((Integer) evt.getNewValue()); } public boolean verify(int count, List eventslist, List valueslist) { return (count == firecount) && events.equals(eventslist) && newvalues.equals(valueslist); } public boolean verify(int count, List eventslist) { return (count == firecount) && events.equals(eventslist); } public void reset() { firecount = 0; events.clear(); newvalues.clear(); } }