From dcc68fa0a9fb37742db5a4352ff2be287cc7cae7 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 18 Feb 2021 18:42:42 +0000 Subject: [PATCH] JAL-3822 pass panel height and width to wrapped geometry calculations --- src/jalview/gui/SeqCanvas.java | 2 +- src/jalview/gui/SeqPanel.java | 6 ++ test/jalview/gui/SeqPanelTest.java | 178 +++++++++++++++++++++++++++++++++--- 3 files changed, 174 insertions(+), 12 deletions(-) diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index b27208a..a9b9d4d 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -456,7 +456,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI if (av.getWrapAlignment()) { - drawWrappedPanel(gg, width, height, ranges.getStartRes()); + drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes()); } else { diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index 4ffefba..163ae25 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -275,6 +275,9 @@ public class SeqPanel extends JPanel /** * Computes the column and sequence row (and possibly annotation row when in * wrapped mode) for the given mouse position + *

+ * Mouse position is not set if in wrapped mode with the cursor either between + * sequences, or over the left or right vertical scale. * * @param evt * @return @@ -342,6 +345,9 @@ public class SeqPanel extends JPanel /** * Returns the aligned sequence position (base 0) at the mouse position, or * the closest visible one + *

+ * Returns -1 if in wrapped mode with the mouse over either left or right + * vertical scale. * * @param evt * @return diff --git a/test/jalview/gui/SeqPanelTest.java b/test/jalview/gui/SeqPanelTest.java index a03819d..b0fc116 100644 --- a/test/jalview/gui/SeqPanelTest.java +++ b/test/jalview/gui/SeqPanelTest.java @@ -24,6 +24,17 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; +import java.awt.EventQueue; +import java.awt.FontMetrics; +import java.awt.event.MouseEvent; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.JLabel; + +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + import jalview.api.AlignViewportI; import jalview.bin.Cache; import jalview.bin.Jalview; @@ -33,6 +44,8 @@ import jalview.commands.EditCommand.Edit; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; +import jalview.datamodel.SearchResults; +import jalview.datamodel.SearchResultsI; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceI; import jalview.gui.SeqPanel.MousePos; @@ -40,17 +53,6 @@ import jalview.io.DataSourceType; import jalview.io.FileLoader; import jalview.util.MessageManager; import jalview.viewmodel.ViewportRanges; - -import java.awt.EventQueue; -import java.awt.event.MouseEvent; -import java.lang.reflect.InvocationTargetException; - -import javax.swing.JLabel; - -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - import junit.extensions.PA; public class SeqPanelTest @@ -635,6 +637,7 @@ public class SeqPanelTest { Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false"); Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true"); + Cache.applicationProperties.setProperty("FONT_SIZE", "10"); AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded( "examples/uniref50.fa", DataSourceType.FILE); AlignViewportI av = alignFrame.getViewport(); @@ -902,4 +905,157 @@ public class SeqPanelTest e.printStackTrace(); } } + @Test(groups = "Functional") + public void testFindMousePosition_wrapped_scales_longSequence() + { + Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false"); + Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true"); + Cache.applicationProperties.setProperty("FONT_SIZE", "14"); + Cache.applicationProperties.setProperty("FONT_NAME", "SansSerif"); + Cache.applicationProperties.setProperty("FONT_STYLE", "0"); + // sequence of 50 bases, doubled 10 times, = 51200 bases + String dna = "ATGGCCATTGGGCCCAAATTTCCCAAAGGGTTTCCCTGAGGTCAGTCAGA"; + for (int i = 0 ; i < 10 ; i++) + { + dna += dna; + } + assertEquals(dna.length(), 51200); + AlignFrame alignFrame = new FileLoader() + .LoadFileWaitTillLoaded(dna, DataSourceType.PASTE); + SeqPanel testee = alignFrame.alignPanel.getSeqPanel(); + AlignViewport av = alignFrame.getViewport(); + av.setScaleAboveWrapped(true); + av.setScaleLeftWrapped(true); + av.setScaleRightWrapped(true); + alignFrame.alignPanel.updateLayout(); + + try + { + Thread.sleep(200); + } catch (InterruptedException e) + { + } + + final int charHeight = av.getCharHeight(); + final int charWidth = av.getCharWidth(); + assertEquals(charHeight, 17); + assertEquals(charWidth, 12); + + FontMetrics fm = testee.getFontMetrics(av.getFont()); + int labelWidth = fm.stringWidth("00000") + charWidth; + assertEquals(labelWidth, 57); // 5 x 9 + charWidth + assertEquals(testee.seqCanvas.getLabelWidthWest(), labelWidth); + + int x = 0; + int y = 0; + + /* + * mouse at top left of wrapped panel; there is a gap of 2 * charHeight + * above the alignment + */ + MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, + 0, 0, 0, false, 0); + MousePos pos = testee.findMousePosition(evt); + assertEquals(pos.column, -1); // over scale left, not an alignment column + assertEquals(pos.seqIndex, -1); // above sequences + assertEquals(pos.annotationIndex, -1); + + /* + * cursor over scale above first sequence + */ + y += charHeight; + x = labelWidth; + evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0, + false, 0); + pos = testee.findMousePosition(evt); + assertEquals(pos.seqIndex, -1); + assertEquals(pos.column, 0); + assertEquals(pos.annotationIndex, -1); + + /* + * cursor over scale left of first sequence + */ + y += charHeight; + x = 0; + evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0, + false, 0); + pos = testee.findMousePosition(evt); + assertEquals(pos.seqIndex, 0); + assertEquals(pos.column, -1); + assertEquals(pos.annotationIndex, -1); + + /* + * cursor over start of first sequence + */ + x = labelWidth; + evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0, + false, 0); + pos = testee.findMousePosition(evt); + assertEquals(pos.seqIndex, 0); + assertEquals(pos.column, 0); + assertEquals(pos.annotationIndex, -1); + + /* + * move one character right, to bottom pixel of same row + */ + x += charWidth; + y += charHeight - 1; + evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0, + false, 0); + pos = testee.findMousePosition(evt); + assertEquals(pos.seqIndex, 0); + assertEquals(pos.column, 1); + + /* + * move down one pixel - now in the no man's land between rows + */ + y += 1; + evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0, + false, 0); + pos = testee.findMousePosition(evt); + assertEquals(pos.seqIndex, -1); + assertEquals(pos.column, 1); + + /* + * move down two char heights less one pixel - still in the no man's land + * (scale above + spacer line) + */ + y += (2 * charHeight - 1); + evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0, + false, 0); + pos = testee.findMousePosition(evt); + assertEquals(pos.seqIndex, -1); + assertEquals(pos.column, 1); + + /* + * move down one more pixel - now on the next row of the sequence + */ + y += 1; + evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0, + false, 0); + pos = testee.findMousePosition(evt); + assertEquals(pos.seqIndex, 0); + assertEquals(pos.column, 1 + av.getWrappedWidth()); + + /* + * scroll to near the end of the sequence + */ + SearchResultsI sr = new SearchResults(); + int scrollTo = dna.length() - 1000; + sr.addResult(av.getAlignment().getSequenceAt(0), scrollTo, scrollTo); + alignFrame.alignPanel.scrollToPosition(sr); + + /* + * place the mouse on the first column of the 6th sequence, and + * verify that (computed) findMousePosition matches (actual) ViewportRanges + */ + x = labelWidth; + y = 17 * charHeight; // 17 = 6 times two header rows and 5 sequence rows + evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0, + false, 0); + pos = testee.findMousePosition(evt); + assertEquals(pos.seqIndex, 0); + int expected = av.getRanges().getStartRes() + 5 * av.getWrappedWidth(); + assertEquals(pos.column, expected); + } } -- 1.7.10.2