From f484ffbf14ae725e55c80396be1889708988fd8b Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 4 Oct 2018 11:38:48 +0100 Subject: [PATCH] JAL-3093 unit tests, no mouse action over left/right wrapped scale --- src/jalview/gui/SeqPanel.java | 103 ++++++++----------- test/jalview/gui/SeqPanelTest.java | 195 ++++++++++++++++++++++++++++++++++-- 2 files changed, 230 insertions(+), 68 deletions(-) diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index d0859b8..a53edb9 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -274,23 +274,9 @@ public class SeqPanel extends JPanel { seqCanvas.calculateWrappedGeometry(seqCanvas.getWidth(), seqCanvas.getHeight()); - // int gapHeight = charHeight; - // if (av.getScaleAboveWrapped()) - // { - // gapHeight += charHeight; - // } - // - // final int alignmentHeightPixels = gapHeight - // + alignmentHeight * charHeight; - // int cHeight = alignmentHeightPixels; - // if (av.isShowAnnotation()) - // { - // cHeight += (seqCanvas.getAnnotationHeight() + - // SeqCanvas.SEQS_ANNOTATION_GAP); - // } /* - * yPos modulo repeating width height + * yPos modulo height of repeating width */ int yOffsetPx = y % seqCanvas.wrappedRepeatHeightPx; @@ -345,7 +331,9 @@ public class SeqPanel extends JPanel int res = 0; int x = evt.getX(); - int startRes = av.getRanges().getStartRes(); + final int startRes = av.getRanges().getStartRes(); + final int charWidth = av.getCharWidth(); + if (av.getWrapAlignment()) { int hgap = av.getCharHeight(); @@ -359,20 +347,30 @@ public class SeqPanel extends JPanel int y = evt.getY(); y = Math.max(0, y - hgap); - x = Math.max(0, x - seqCanvas.getLabelWidthWest()); + x -= seqCanvas.getLabelWidthWest(); + if (x < 0) + { + // mouse is over left scale + return -1; + } int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth()); if (cwidth < 1) { return 0; } + if (x >= cwidth * charWidth) + { + // mouse is over right scale + return -1; + } wrappedBlock = y / cHeight; wrappedBlock += startRes / cwidth; // allow for wrapped view scrolled right (possible from Overview) int startOffset = startRes % cwidth; res = wrappedBlock * cwidth + startOffset - + Math.min(cwidth - 1, x / av.getCharWidth()); + + Math.min(cwidth - 1, x / charWidth); } else { @@ -381,7 +379,7 @@ public class SeqPanel extends JPanel * rather than right-hand gutter */ x = Math.min(x, seqCanvas.getX() + seqCanvas.getWidth()); - res = (x / av.getCharWidth()) + startRes; + res = (x / charWidth) + startRes; res = Math.min(res, av.getRanges().getEndRes()); } @@ -728,9 +726,8 @@ public class SeqPanel extends JPanel public void mouseReleased(MouseEvent evt) { MousePos pos = findMousePosition(evt); - if (pos.annotationIndex != -1) + if (pos.isOverAnnotation() || pos.seqIndex == -1 || pos.column == -1) { - // mouse is over annotation row in wrapped mode return; } @@ -765,9 +762,8 @@ public class SeqPanel extends JPanel { lastMousePress = evt.getPoint(); MousePos pos = findMousePosition(evt); - if (pos.annotationIndex != -1) + if (pos.isOverAnnotation() || pos.seqIndex == -1 || pos.column == -1) { - // mouse is over an annotation row in wrapped mode return; } @@ -795,11 +791,6 @@ public class SeqPanel extends JPanel int seq = pos.seqIndex; int res = pos.column; - if (seq < 0 || res < 0) - { - return; - } - if ((seq < av.getAlignment().getHeight()) && (res < av.getAlignment().getSequenceAt(seq).getLength())) { @@ -923,7 +914,7 @@ public class SeqPanel extends JPanel lastMousePosition = null; setToolTipText(null); lastTooltip = null; - ap.alignFrame.statusBar.setText(""); + ap.alignFrame.setStatus(""); return; } @@ -1015,7 +1006,8 @@ public class SeqPanel extends JPanel final int column = pos.column; final int rowIndex = pos.annotationIndex; - if (!av.getWrapAlignment() || !av.isShowAnnotation() || rowIndex < 0) + if (column < 0 || !av.getWrapAlignment() || !av.isShowAnnotation() + || rowIndex < 0) { return; } @@ -1028,7 +1020,7 @@ public class SeqPanel extends JPanel String msg = AnnotationPanel.getStatusMessage(av.getAlignment(), column, anns[rowIndex]); - ap.alignFrame.statusBar.setText(msg); + ap.alignFrame.setStatus(msg); } private Point lastp = null; @@ -1163,7 +1155,7 @@ public class SeqPanel extends JPanel text.append(" (").append(Integer.toString(residuePos)).append(")"); } - ap.alignFrame.statusBar.setText(text.toString()); + ap.alignFrame.setStatus(text.toString()); } /** @@ -1206,9 +1198,8 @@ public class SeqPanel extends JPanel public void mouseDragged(MouseEvent evt) { MousePos pos = findMousePosition(evt); - if (pos.isOverAnnotation()) + if (pos.isOverAnnotation() || pos.column == -1) { - // mouse is over annotation row in wrapped mode return; } @@ -1307,7 +1298,7 @@ public class SeqPanel extends JPanel if (!editingSeqs) { - doMouseDraggedDefineMode(evt); + dragStretchGroup(evt); return; } @@ -1397,7 +1388,7 @@ public class SeqPanel extends JPanel } message.append(Math.abs(startres - lastres) + " gaps."); - ap.alignFrame.statusBar.setText(message.toString()); + ap.alignFrame.setStatus(message.toString()); // Are we editing within a selection group? if (groupEditing || (sg != null @@ -1777,6 +1768,7 @@ public class SeqPanel extends JPanel @Override public void mouseExited(MouseEvent e) { + ap.alignFrame.setStatus(" "); if (av.getWrapAlignment()) { return; @@ -1798,9 +1790,8 @@ public class SeqPanel extends JPanel { SequenceGroup sg = null; MousePos pos = findMousePosition(evt); - if (pos.isOverAnnotation()) + if (pos.isOverAnnotation() || pos.seqIndex == -1 || pos.column == -1) { - // mouse is over annotation label in wrapped mode return; } @@ -1819,7 +1810,7 @@ public class SeqPanel extends JPanel * find features at the position (if not gapped), or straddling * the position (if at a gap) */ - SequenceI sequence = av.getAlignment().getSequenceAt(pos.seqIndex);// findSeq(evt)); + SequenceI sequence = av.getAlignment().getSequenceAt(pos.seqIndex); List features = seqCanvas.getFeatureRenderer() .findFeaturesAtColumn(sequence, column + 1); @@ -1891,13 +1882,8 @@ public class SeqPanel extends JPanel */ protected void doMousePressedDefineMode(MouseEvent evt, MousePos pos) { - if (pos.isOverAnnotation()) + if (pos.isOverAnnotation() || pos.seqIndex == -1 || pos.column == -1) { - // JvOptionPane.showInternalMessageDialog(Desktop.desktop, - // MessageManager.getString( - // "label.cannot_edit_annotations_in_wrapped_view"), - // MessageManager.getString("label.wrapped_view_no_edit"), - // JvOptionPane.WARNING_MESSAGE); return; } @@ -1908,11 +1894,6 @@ public class SeqPanel extends JPanel startWrapBlock = wrappedBlock; - if (seq < 0 || res < 0) - { - return; - } - SequenceI sequence = av.getAlignment().getSequenceAt(seq); if ((sequence == null) || (res > sequence.getLength())) @@ -2035,7 +2016,8 @@ public class SeqPanel extends JPanel * true if this event is happening after a mouse drag (rather than a * mouse down) */ - public void doMouseReleasedDefineMode(MouseEvent evt, boolean afterDrag) + protected void doMouseReleasedDefineMode(MouseEvent evt, + boolean afterDrag) { if (stretchGroup == null) { @@ -2078,17 +2060,21 @@ public class SeqPanel extends JPanel } /** - * DOCUMENT ME! + * Resizes the borders of a selection group depending on the direction of + * mouse drag * * @param evt - * DOCUMENT ME! */ - public void doMouseDraggedDefineMode(MouseEvent evt) + protected void dragStretchGroup(MouseEvent evt) { + if (stretchGroup == null) + { + return; + } + MousePos pos = findMousePosition(evt); - if (pos.isOverAnnotation()) + if (pos.isOverAnnotation() || pos.column == -1 || pos.seqIndex == -1) { - // mouse is over annotation in wrapped mode return; } @@ -2100,11 +2086,6 @@ public class SeqPanel extends JPanel return; } - if (stretchGroup == null) - { - return; - } - if (res >= av.getAlignment().getWidth()) { res = av.getAlignment().getWidth() - 1; diff --git a/test/jalview/gui/SeqPanelTest.java b/test/jalview/gui/SeqPanelTest.java index d5c012e..d2344cc 100644 --- a/test/jalview/gui/SeqPanelTest.java +++ b/test/jalview/gui/SeqPanelTest.java @@ -37,10 +37,14 @@ import jalview.io.FileLoader; import java.awt.Event; import java.awt.event.MouseEvent; +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 { AlignFrame af; @@ -65,22 +69,24 @@ public class SeqPanelTest assertEquals( alignFrame.alignPanel.getSeqPanel().setStatusMessage( visAl.getSequenceAt(1), 1, 1), 2); - assertEquals(alignFrame.statusBar.getText(), + assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(), "Sequence 2 ID: Seq2 Residue: ALA (2)"); assertEquals( alignFrame.alignPanel.getSeqPanel().setStatusMessage( visAl.getSequenceAt(1), 4, 1), 3); - assertEquals(alignFrame.statusBar.getText(), + assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(), "Sequence 2 ID: Seq2 Residue: GLU (3)"); // no status message at a gap, returns next residue position to the right assertEquals( alignFrame.alignPanel.getSeqPanel().setStatusMessage( visAl.getSequenceAt(1), 2, 1), 3); - assertEquals(alignFrame.statusBar.getText(), "Sequence 2 ID: Seq2"); + assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(), + "Sequence 2 ID: Seq2"); assertEquals( alignFrame.alignPanel.getSeqPanel().setStatusMessage( visAl.getSequenceAt(1), 3, 1), 3); - assertEquals(alignFrame.statusBar.getText(), "Sequence 2 ID: Seq2"); + assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(), + "Sequence 2 ID: Seq2"); } @Test(groups = "Functional") @@ -96,7 +102,7 @@ public class SeqPanelTest assertEquals( alignFrame.alignPanel.getSeqPanel().setStatusMessage( visAl.getSequenceAt(1), 1, 1), 2); - assertEquals(alignFrame.statusBar.getText(), + assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(), "Sequence 2 ID: Seq2 Residue: B (2)"); } @@ -149,6 +155,7 @@ public class SeqPanelTest av.setScaleLeftWrapped(false); av.setScaleRightWrapped(false); alignFrame.alignPanel.paintAlignment(false, false); + waitForSwing(); // for Swing thread final int charHeight = av.getCharHeight(); final int charWidth = av.getCharWidth(); @@ -358,7 +365,8 @@ public class SeqPanelTest av.setScaleLeftWrapped(false); av.setScaleRightWrapped(false); alignFrame.alignPanel.paintAlignment(false, false); - + waitForSwing(); + final int charHeight = av.getCharHeight(); final int charWidth = av.getCharWidth(); final int alignmentHeight = av.getAlignment().getHeight(); @@ -576,6 +584,7 @@ public class SeqPanelTest assertEquals(pos.seqIndex, 0); assertEquals(pos.annotationIndex, -1); } + @Test(groups = "Functional") public void testFindMousePosition_wrapped_noAnnotations() { @@ -588,7 +597,8 @@ public class SeqPanelTest av.setScaleLeftWrapped(false); av.setScaleRightWrapped(false); alignFrame.alignPanel.paintAlignment(false, false); - + waitForSwing(); + final int charHeight = av.getCharHeight(); final int charWidth = av.getCharWidth(); final int alignmentHeight = av.getAlignment().getHeight(); @@ -663,6 +673,163 @@ public class SeqPanelTest assertEquals(pos.seqIndex, 0); assertEquals(pos.annotationIndex, -1); } + + @Test(groups = "Functional") + public void testFindColumn_unwrapped() + { + Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "false"); + AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded( + "examples/uniref50.fa", DataSourceType.FILE); + SeqPanel testee = alignFrame.alignPanel.getSeqPanel(); + int x = 0; + final int charWidth = alignFrame.getViewport().getCharWidth(); + assertTrue(charWidth > 0); // sanity check + assertEquals(alignFrame.getViewport().getRanges().getStartRes(), 0); + + /* + * mouse at top left of unwrapped panel + */ + MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, + 0, 0, 0, false, 0); + assertEquals(testee.findColumn(evt), 0); + + /* + * not quite one charWidth across + */ + x = charWidth-1; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, + 0, 0, 0, false, 0); + assertEquals(testee.findColumn(evt), 0); + + /* + * one charWidth across + */ + x = charWidth; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + assertEquals(testee.findColumn(evt), 1); + + /* + * two charWidths across + */ + x = 2 * charWidth; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + assertEquals(testee.findColumn(evt), 2); + + /* + * limited to last column of seqcanvas + */ + x = 20000; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + SeqCanvas seqCanvas = alignFrame.alignPanel.getSeqPanel().seqCanvas; + int w = seqCanvas.getWidth(); + // limited to number of whole columns, base 0 + int expected = w / charWidth - 1; + assertEquals(testee.findColumn(evt), expected); + + /* + * hide columns 5-10 (base 1) + */ + alignFrame.getViewport().hideColumns(4, 9); + x = 5 * charWidth + 2; + // x is in 6th visible column, absolute column 12, or 11 base 0 + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + assertEquals(testee.findColumn(evt), 11); + } + + @Test(groups = "Functional") + public void testFindColumn_wrapped() + { + Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true"); + AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded( + "examples/uniref50.fa", DataSourceType.FILE); + AlignViewport av = alignFrame.getViewport(); + av.setScaleAboveWrapped(false); + av.setScaleLeftWrapped(false); + av.setScaleRightWrapped(false); + alignFrame.alignPanel.paintAlignment(false, false); + // need to wait for repaint to finish! + waitForSwing(); + SeqPanel testee = alignFrame.alignPanel.getSeqPanel(); + int x = 0; + final int charWidth = av.getCharWidth(); + assertTrue(charWidth > 0); // sanity check + assertEquals(av.getRanges().getStartRes(), 0); + + /* + * mouse at top left of wrapped panel, no West (left) scale + */ + MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, + 0, 0, 0, false, 0); + assertEquals(testee.findColumn(evt), 0); + + /* + * not quite one charWidth across + */ + x = charWidth-1; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, + 0, 0, 0, false, 0); + assertEquals(testee.findColumn(evt), 0); + + /* + * one charWidth across + */ + x = charWidth; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + assertEquals(testee.findColumn(evt), 1); + + /* + * x over scale left (before drawn columns) results in -1 + */ + av.setScaleLeftWrapped(true); + alignFrame.alignPanel.paintAlignment(false, false); + waitForSwing(); + SeqCanvas seqCanvas = testee.seqCanvas; + int labelWidth = (int) PA.getValue(seqCanvas, "labelWidthWest"); + assertTrue(labelWidth > 0); + x = labelWidth - 1; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + assertEquals(testee.findColumn(evt), -1); + + x = labelWidth; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + assertEquals(testee.findColumn(evt), 0); + + /* + * x over right edge of last residue (including scale left) + */ + int residuesWide = av.getRanges().getViewportWidth(); + assertTrue(residuesWide > 0); + x = labelWidth + charWidth * residuesWide - 1; + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + assertEquals(testee.findColumn(evt), residuesWide - 1); + + /* + * x over scale right (beyond drawn columns) results in -1 + */ + av.setScaleRightWrapped(true); + alignFrame.alignPanel.paintAlignment(false, false); + waitForSwing(); + labelWidth = (int) PA.getValue(seqCanvas, "labelWidthEast"); + assertTrue(labelWidth > 0); + int residuesWide2 = av.getRanges().getViewportWidth(); + assertTrue(residuesWide2 > 0); + assertTrue(residuesWide2 < residuesWide); // available width reduced + x += 1; // just over left edge of scale right + evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0, + false, 0); + assertEquals(testee.findColumn(evt), -1); + + // todo add startRes offset, hidden columns + + } @BeforeClass(alwaysRun = true) public static void setUpBeforeClass() throws Exception { @@ -672,4 +839,18 @@ public class SeqPanelTest Cache.loadProperties("test/jalview/io/testProps.jvprops"); Jalview.main(new String[] { "-nonews" }); } + + /** + * waits a few ms for Swing to do something + */ + synchronized void waitForSwing() + { + try + { + super.wait(10); + } catch (InterruptedException e) + { + e.printStackTrace(); + } + } } -- 1.7.10.2