2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertNull;
25 import static org.testng.Assert.assertTrue;
27 import java.awt.EventQueue;
28 import java.awt.FontMetrics;
29 import java.awt.event.MouseEvent;
30 import java.lang.reflect.InvocationTargetException;
32 import javax.swing.JLabel;
34 import org.testng.annotations.AfterMethod;
35 import org.testng.annotations.BeforeClass;
36 import org.testng.annotations.Test;
38 import jalview.api.AlignViewportI;
39 import jalview.bin.Cache;
40 import jalview.bin.Jalview;
41 import jalview.commands.EditCommand;
42 import jalview.commands.EditCommand.Action;
43 import jalview.commands.EditCommand.Edit;
44 import jalview.datamodel.Alignment;
45 import jalview.datamodel.AlignmentAnnotation;
46 import jalview.datamodel.AlignmentI;
47 import jalview.datamodel.SearchResults;
48 import jalview.datamodel.SearchResultsI;
49 import jalview.datamodel.Sequence;
50 import jalview.datamodel.SequenceI;
51 import jalview.gui.SeqPanel.MousePos;
52 import jalview.io.DataSourceType;
53 import jalview.io.FileLoader;
54 import jalview.util.MessageManager;
55 import jalview.viewmodel.ViewportRanges;
56 import junit.extensions.PA;
58 public class SeqPanelTest
62 @BeforeClass(alwaysRun = true)
63 public void setUpJvOptionPane()
65 JvOptionPane.setInteractiveMode(false);
66 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
69 @Test(groups = "Functional")
70 public void testSetStatusReturnsNearestResiduePosition()
72 SequenceI seq1 = new Sequence("Seq1", "AACDE");
73 SequenceI seq2 = new Sequence("Seq2", "AA--E");
74 AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
75 AlignFrame alignFrame = new AlignFrame(al, al.getWidth(),
77 AlignmentI visAl = alignFrame.getViewport().getAlignment();
79 // Test either side of gap
80 assertEquals(alignFrame.alignPanel.getSeqPanel()
81 .setStatusMessage(visAl.getSequenceAt(1), 1, 1), 2);
82 assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
83 "Sequence 2 ID: Seq2 Residue: ALA (2)");
84 assertEquals(alignFrame.alignPanel.getSeqPanel()
85 .setStatusMessage(visAl.getSequenceAt(1), 4, 1), 3);
86 assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
87 "Sequence 2 ID: Seq2 Residue: GLU (3)");
88 // no status message at a gap, returns next residue position to the right
89 assertEquals(alignFrame.alignPanel.getSeqPanel()
90 .setStatusMessage(visAl.getSequenceAt(1), 2, 1), 3);
91 assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
92 "Sequence 2 ID: Seq2");
93 assertEquals(alignFrame.alignPanel.getSeqPanel()
94 .setStatusMessage(visAl.getSequenceAt(1), 3, 1), 3);
95 assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
96 "Sequence 2 ID: Seq2");
99 @Test(groups = "Functional")
100 public void testAmbiguousAminoAcidGetsStatusMessage()
102 SequenceI seq1 = new Sequence("Seq1", "ABCDE");
103 SequenceI seq2 = new Sequence("Seq2", "AB--E");
104 AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
105 AlignFrame alignFrame = new AlignFrame(al, al.getWidth(),
107 AlignmentI visAl = alignFrame.getViewport().getAlignment();
109 assertEquals(alignFrame.alignPanel.getSeqPanel()
110 .setStatusMessage(visAl.getSequenceAt(1), 1, 1), 2);
111 assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
112 "Sequence 2 ID: Seq2 Residue: B (2)");
115 @Test(groups = "Functional")
116 public void testGetEditStatusMessage()
118 assertNull(SeqPanel.getEditStatusMessage(null));
120 EditCommand edit = new EditCommand(); // empty
121 assertNull(SeqPanel.getEditStatusMessage(edit));
123 SequenceI[] seqs = new SequenceI[] { new Sequence("a", "b") };
126 edit.addEdit(edit.new Edit(Action.INSERT_GAP, seqs, 1, 1, '-'));
127 String expected = MessageManager.formatMessage("label.insert_gap", "1");
128 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
130 // 3 more gaps makes +4
131 edit.addEdit(edit.new Edit(Action.INSERT_GAP, seqs, 1, 3, '-'));
132 expected = MessageManager.formatMessage("label.insert_gaps", "4");
133 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
135 // 2 deletes makes + 2
136 edit.addEdit(edit.new Edit(Action.DELETE_GAP, seqs, 1, 2, '-'));
137 expected = MessageManager.formatMessage("label.insert_gaps", "2");
138 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
140 // 2 more deletes makes 0 - no text
141 edit.addEdit(edit.new Edit(Action.DELETE_GAP, seqs, 1, 2, '-'));
142 assertNull(SeqPanel.getEditStatusMessage(edit));
144 // 1 more delete makes 1 delete
145 edit.addEdit(edit.new Edit(Action.DELETE_GAP, seqs, 1, 1, '-'));
146 expected = MessageManager.formatMessage("label.delete_gap", "1");
147 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
149 // 1 more delete makes 2 deletes
150 edit.addEdit(edit.new Edit(Action.DELETE_GAP, seqs, 1, 1, '-'));
151 expected = MessageManager.formatMessage("label.delete_gaps", "2");
152 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
156 * Tests that simulate 'locked editing', where an inserted gap is balanced by
157 * a gap deletion in the selection group, and vice versa
159 @Test(groups = "Functional")
160 public void testGetEditStatusMessage_lockedEditing()
162 EditCommand edit = new EditCommand(); // empty
163 SequenceI[] seqs = new SequenceI[] { new Sequence("a", "b") };
165 // 1 gap inserted, balanced by 1 delete
166 Edit e1 = edit.new Edit(Action.INSERT_GAP, seqs, 1, 1, '-');
168 Edit e2 = edit.new Edit(Action.DELETE_GAP, seqs, 5, 1, '-');
169 e2.setSystemGenerated(true);
171 String expected = MessageManager.formatMessage("label.insert_gap", "1");
172 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
174 // 2 more gaps makes +3
175 Edit e3 = edit.new Edit(Action.INSERT_GAP, seqs, 1, 2, '-');
177 Edit e4 = edit.new Edit(Action.DELETE_GAP, seqs, 5, 2, '-');
178 e4.setSystemGenerated(true);
180 expected = MessageManager.formatMessage("label.insert_gaps", "3");
181 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
183 // 2 deletes makes + 1
184 Edit e5 = edit.new Edit(Action.DELETE_GAP, seqs, 1, 2, '-');
186 Edit e6 = edit.new Edit(Action.INSERT_GAP, seqs, 5, 2, '-');
187 e6.setSystemGenerated(true);
189 expected = MessageManager.formatMessage("label.insert_gap", "1");
190 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
192 // 1 more delete makes 0 - no text
193 Edit e7 = edit.new Edit(Action.DELETE_GAP, seqs, 1, 1, '-');
195 Edit e8 = edit.new Edit(Action.INSERT_GAP, seqs, 5, 1, '-');
196 e8.setSystemGenerated(true);
198 expected = MessageManager.formatMessage("label.insert_gaps", "2");
199 assertNull(SeqPanel.getEditStatusMessage(edit));
201 // 1 more delete makes 1 delete
202 Edit e9 = edit.new Edit(Action.DELETE_GAP, seqs, 1, 1, '-');
204 Edit e10 = edit.new Edit(Action.INSERT_GAP, seqs, 5, 1, '-');
205 e10.setSystemGenerated(true);
207 expected = MessageManager.formatMessage("label.delete_gap", "1");
208 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
210 // 2 more deletes makes 3 deletes
211 Edit e11 = edit.new Edit(Action.DELETE_GAP, seqs, 1, 2, '-');
213 Edit e12 = edit.new Edit(Action.INSERT_GAP, seqs, 5, 2, '-');
214 e12.setSystemGenerated(true);
216 expected = MessageManager.formatMessage("label.delete_gaps", "3");
217 assertEquals(SeqPanel.getEditStatusMessage(edit), expected);
220 public void testFindMousePosition_unwrapped()
222 String seqData = ">Seq1\nAACDE\n>Seq2\nAA--E\n";
223 AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(seqData,
224 DataSourceType.PASTE);
225 AlignViewportI av = alignFrame.getViewport();
226 av.setShowAnnotation(true);
227 av.setWrapAlignment(false);
228 final int charHeight = av.getCharHeight();
229 final int charWidth = av.getCharWidth();
231 assertTrue(charHeight > 0);
232 assertTrue(charWidth > 0);
233 assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
235 SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
240 * mouse at top left of unwrapped panel
242 MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0,
243 x, y, 0, 0, 0, false, 0);
244 MousePos pos = testee.findMousePosition(evt);
245 assertEquals(pos.column, 0);
246 assertEquals(pos.seqIndex, 0);
247 assertEquals(pos.annotationIndex, -1);
250 @AfterMethod(alwaysRun = true)
251 public void tearDown()
253 Desktop.instance.closeAll_actionPerformed(null);
256 @Test(groups = "Functional")
257 public void testFindMousePosition_wrapped_annotations()
259 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "true");
260 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
261 AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
262 "examples/uniref50.fa", DataSourceType.FILE);
263 AlignViewportI av = alignFrame.getViewport();
264 av.setScaleAboveWrapped(false);
265 av.setScaleLeftWrapped(false);
266 av.setScaleRightWrapped(false);
268 alignFrame.alignPanel.updateLayout();
270 final int charHeight = av.getCharHeight();
271 final int charWidth = av.getCharWidth();
272 final int alignmentHeight = av.getAlignment().getHeight();
275 assertTrue(charHeight > 0);
276 assertTrue(charWidth > 0);
277 assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
279 SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
284 * mouse at top left of wrapped panel; there is a gap of charHeight
285 * above the alignment
287 MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0,
288 x, y, 0, 0, 0, false, 0);
289 MousePos pos = testee.findMousePosition(evt);
290 assertEquals(pos.column, 0);
291 assertEquals(pos.seqIndex, -1); // above sequences
292 assertEquals(pos.annotationIndex, -1);
295 * cursor at bottom of gap above
298 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
300 pos = testee.findMousePosition(evt);
301 assertEquals(pos.seqIndex, -1);
302 assertEquals(pos.annotationIndex, -1);
305 * cursor over top of first sequence
308 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
310 pos = testee.findMousePosition(evt);
311 assertEquals(pos.seqIndex, 0);
312 assertEquals(pos.annotationIndex, -1);
315 * cursor at bottom of first sequence
317 y = 2 * charHeight - 1;
318 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
320 pos = testee.findMousePosition(evt);
321 assertEquals(pos.seqIndex, 0);
322 assertEquals(pos.annotationIndex, -1);
325 * cursor at top of second sequence
328 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
330 pos = testee.findMousePosition(evt);
331 assertEquals(pos.seqIndex, 1);
332 assertEquals(pos.annotationIndex, -1);
335 * cursor at bottom of second sequence
337 y = 3 * charHeight - 1;
338 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
340 pos = testee.findMousePosition(evt);
341 assertEquals(pos.seqIndex, 1);
342 assertEquals(pos.annotationIndex, -1);
345 * cursor at bottom of last sequence
347 y = charHeight * (1 + alignmentHeight) - 1;
348 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
350 pos = testee.findMousePosition(evt);
351 assertEquals(pos.seqIndex, alignmentHeight - 1);
352 assertEquals(pos.annotationIndex, -1);
355 * cursor below sequences, in 3-pixel gap above annotations
356 * method reports index of nearest sequence above
359 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
361 pos = testee.findMousePosition(evt);
362 assertEquals(pos.seqIndex, alignmentHeight - 1);
363 assertEquals(pos.annotationIndex, -1);
366 * cursor still in the gap above annotations, now at the bottom of it
368 y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
369 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
371 pos = testee.findMousePosition(evt);
372 assertEquals(pos.seqIndex, alignmentHeight - 1);
373 assertEquals(pos.annotationIndex, -1);
375 AlignmentAnnotation[] annotationRows = av.getAlignment()
376 .getAlignmentAnnotation();
377 for (int n = 0; n < annotationRows.length; n++)
380 * cursor at the top of the n'th annotation
383 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0,
385 pos = testee.findMousePosition(evt);
386 assertEquals(pos.seqIndex, alignmentHeight - 1);
387 assertEquals(pos.annotationIndex, n); // over n'th annotation
390 * cursor at the bottom of the n'th annotation
392 y += annotationRows[n].height - 1;
393 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0,
395 pos = testee.findMousePosition(evt);
396 assertEquals(pos.seqIndex, alignmentHeight - 1);
397 assertEquals(pos.annotationIndex, n);
401 * cursor in gap between wrapped widths
404 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
406 pos = testee.findMousePosition(evt);
407 assertEquals(pos.seqIndex, -1);
408 assertEquals(pos.annotationIndex, -1);
411 * cursor at bottom of gap between wrapped widths
414 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
416 pos = testee.findMousePosition(evt);
417 assertEquals(pos.seqIndex, -1);
418 assertEquals(pos.annotationIndex, -1);
421 * cursor at top of first sequence, second wrapped width
424 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
426 pos = testee.findMousePosition(evt);
427 assertEquals(pos.seqIndex, 0);
428 assertEquals(pos.annotationIndex, -1);
431 @Test(groups = "Functional")
432 public void testFindMousePosition_wrapped_scaleAbove()
434 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "true");
435 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
436 AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
437 "examples/uniref50.fa", DataSourceType.FILE);
438 AlignViewportI av = alignFrame.getViewport();
439 av.setScaleAboveWrapped(true);
440 av.setScaleLeftWrapped(false);
441 av.setScaleRightWrapped(false);
442 alignFrame.alignPanel.updateLayout();
444 final int charHeight = av.getCharHeight();
445 final int charWidth = av.getCharWidth();
446 final int alignmentHeight = av.getAlignment().getHeight();
449 assertTrue(charHeight > 0);
450 assertTrue(charWidth > 0);
451 assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
453 SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
458 * mouse at top left of wrapped panel; there is a gap of charHeight
459 * above the alignment
461 MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0,
462 x, y, 0, 0, 0, false, 0);
463 MousePos pos = testee.findMousePosition(evt);
464 assertEquals(pos.column, 0);
465 assertEquals(pos.seqIndex, -1); // above sequences
466 assertEquals(pos.annotationIndex, -1);
469 * cursor at bottom of gap above
470 * two charHeights including scale panel
472 y = 2 * charHeight - 1;
473 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
475 pos = testee.findMousePosition(evt);
476 assertEquals(pos.seqIndex, -1);
477 assertEquals(pos.annotationIndex, -1);
480 * cursor over top of first sequence
483 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
485 pos = testee.findMousePosition(evt);
486 assertEquals(pos.seqIndex, 0);
487 assertEquals(pos.annotationIndex, -1);
490 * cursor at bottom of first sequence
493 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
495 pos = testee.findMousePosition(evt);
496 assertEquals(pos.seqIndex, 0);
497 assertEquals(pos.annotationIndex, -1);
500 * cursor at top of second sequence
503 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
505 pos = testee.findMousePosition(evt);
506 assertEquals(pos.seqIndex, 1);
507 assertEquals(pos.annotationIndex, -1);
510 * cursor at bottom of second sequence
513 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
515 pos = testee.findMousePosition(evt);
516 assertEquals(pos.seqIndex, 1);
517 assertEquals(pos.annotationIndex, -1);
520 * cursor at bottom of last sequence
521 * (scale + gap + sequences)
523 y = charHeight * (2 + alignmentHeight) - 1;
524 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
526 pos = testee.findMousePosition(evt);
527 assertEquals(pos.seqIndex, alignmentHeight - 1);
528 assertEquals(pos.annotationIndex, -1);
531 * cursor below sequences, in 3-pixel gap above annotations
534 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
536 pos = testee.findMousePosition(evt);
537 assertEquals(pos.seqIndex, alignmentHeight - 1);
538 assertEquals(pos.annotationIndex, -1);
541 * cursor still in the gap above annotations, now at the bottom of it
542 * method reports index of nearest sequence above
544 y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
545 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
547 pos = testee.findMousePosition(evt);
548 assertEquals(pos.seqIndex, alignmentHeight - 1);
549 assertEquals(pos.annotationIndex, -1);
551 AlignmentAnnotation[] annotationRows = av.getAlignment()
552 .getAlignmentAnnotation();
553 for (int n = 0; n < annotationRows.length; n++)
556 * cursor at the top of the n'th annotation
559 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0,
561 pos = testee.findMousePosition(evt);
562 assertEquals(pos.seqIndex, alignmentHeight - 1);
563 assertEquals(pos.annotationIndex, n); // over n'th annotation
566 * cursor at the bottom of the n'th annotation
568 y += annotationRows[n].height - 1;
569 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0,
571 pos = testee.findMousePosition(evt);
572 SeqCanvas sc = testee.seqCanvas;
573 assertEquals(pos.seqIndex, alignmentHeight - 1,
574 String.format("%s n=%d y=%d %d, %d, %d, %d",
575 annotationRows[n].label, n, y, sc.getWidth(),
576 sc.getHeight(), sc.wrappedRepeatHeightPx,
577 sc.wrappedSpaceAboveAlignment));
578 assertEquals(pos.annotationIndex, n);
582 * cursor in gap between wrapped widths
585 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
587 pos = testee.findMousePosition(evt);
588 assertEquals(pos.seqIndex, -1);
589 assertEquals(pos.annotationIndex, -1);
592 * cursor at bottom of gap between wrapped widths
595 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
597 pos = testee.findMousePosition(evt);
598 assertEquals(pos.seqIndex, -1);
599 assertEquals(pos.annotationIndex, -1);
602 * cursor at top of scale, second wrapped width
605 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
607 pos = testee.findMousePosition(evt);
608 assertEquals(pos.seqIndex, -1);
609 assertEquals(pos.annotationIndex, -1);
612 * cursor at bottom of scale, second wrapped width
615 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
617 pos = testee.findMousePosition(evt);
618 assertEquals(pos.seqIndex, -1);
619 assertEquals(pos.annotationIndex, -1);
622 * cursor at top of first sequence, second wrapped width
625 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
627 pos = testee.findMousePosition(evt);
628 assertEquals(pos.seqIndex, 0);
629 assertEquals(pos.annotationIndex, -1);
632 @Test(groups = "Functional")
633 public void testFindMousePosition_wrapped_noAnnotations()
635 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false");
636 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
637 Cache.applicationProperties.setProperty("FONT_SIZE", "10");
638 AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
639 "examples/uniref50.fa", DataSourceType.FILE);
640 AlignViewportI av = alignFrame.getViewport();
641 av.setScaleAboveWrapped(false);
642 av.setScaleLeftWrapped(false);
643 av.setScaleRightWrapped(false);
644 alignFrame.alignPanel.updateLayout();
646 final int charHeight = av.getCharHeight();
647 final int charWidth = av.getCharWidth();
648 final int alignmentHeight = av.getAlignment().getHeight();
651 assertTrue(charHeight > 0);
652 assertTrue(charWidth > 0);
653 assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
655 SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
660 * mouse at top left of wrapped panel; there is a gap of charHeight
661 * above the alignment
663 MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0,
664 x, y, 0, 0, 0, false, 0);
665 MousePos pos = testee.findMousePosition(evt);
666 assertEquals(pos.column, 0);
667 assertEquals(pos.seqIndex, -1); // above sequences
668 assertEquals(pos.annotationIndex, -1);
671 * cursor over top of first sequence
674 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
676 pos = testee.findMousePosition(evt);
677 assertEquals(pos.seqIndex, 0);
678 assertEquals(pos.annotationIndex, -1);
681 * cursor at bottom of last sequence
683 y = charHeight * (1 + alignmentHeight) - 1;
684 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
686 pos = testee.findMousePosition(evt);
687 assertEquals(pos.seqIndex, alignmentHeight - 1);
688 assertEquals(pos.annotationIndex, -1);
691 * cursor below sequences, at top of charHeight gap between widths
694 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
696 pos = testee.findMousePosition(evt);
697 assertEquals(pos.seqIndex, -1);
698 assertEquals(pos.annotationIndex, -1);
701 * cursor below sequences, at top of charHeight gap between widths
704 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
706 pos = testee.findMousePosition(evt);
707 assertEquals(pos.seqIndex, -1);
708 assertEquals(pos.annotationIndex, -1);
711 * cursor at the top of the first sequence, second width
714 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
716 pos = testee.findMousePosition(evt);
717 assertEquals(pos.seqIndex, 0);
718 assertEquals(pos.annotationIndex, -1);
721 @Test(groups = "Functional")
722 public void testFindColumn_unwrapped()
724 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "false");
725 AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
726 "examples/uniref50.fa", DataSourceType.FILE);
727 SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
729 final int charWidth = alignFrame.getViewport().getCharWidth();
730 assertTrue(charWidth > 0); // sanity check
731 ViewportRanges ranges = alignFrame.getViewport().getRanges();
732 assertEquals(ranges.getStartRes(), 0);
735 * mouse at top left of unwrapped panel
737 MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0,
738 x, 0, 0, 0, 0, false, 0);
739 assertEquals(testee.findColumn(evt), 0);
742 * not quite one charWidth across
745 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
747 assertEquals(testee.findColumn(evt), 0);
750 * one charWidth across
753 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
755 assertEquals(testee.findColumn(evt), 1);
758 * two charWidths across
761 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
763 assertEquals(testee.findColumn(evt), 2);
766 * limited to last column of seqcanvas
769 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
771 SeqCanvas seqCanvas = alignFrame.alignPanel.getSeqPanel().seqCanvas;
772 int w = seqCanvas.getWidth();
773 // limited to number of whole columns, base 0,
774 // and to end of visible range
775 int expected = w / charWidth;
776 expected = Math.min(expected, ranges.getEndRes());
777 assertEquals(testee.findColumn(evt), expected);
780 * hide columns 5-10 (base 1)
782 alignFrame.getViewport().hideColumns(4, 9);
783 x = 5 * charWidth + 2;
784 // x is in 6th visible column, absolute column 12, or 11 base 0
785 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
787 assertEquals(testee.findColumn(evt), 11);
790 @Test(groups = "Functional")
791 public void testFindColumn_wrapped()
793 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
794 AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
795 "examples/uniref50.fa", DataSourceType.FILE);
796 AlignViewport av = alignFrame.getViewport();
797 av.setScaleAboveWrapped(false);
798 av.setScaleLeftWrapped(false);
799 av.setScaleRightWrapped(false);
800 alignFrame.alignPanel.updateLayout();
801 SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
803 final int charWidth = av.getCharWidth();
804 assertTrue(charWidth > 0); // sanity check
805 assertEquals(av.getRanges().getStartRes(), 0);
808 * mouse at top left of wrapped panel, no West (left) scale
810 MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0,
811 x, 0, 0, 0, 0, false, 0);
812 assertEquals(testee.findColumn(evt), 0);
815 * not quite one charWidth across
818 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
820 assertEquals(testee.findColumn(evt), 0);
823 * one charWidth across
826 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
828 assertEquals(testee.findColumn(evt), 1);
831 * x over scale left (before drawn columns) results in -1
833 av.setScaleLeftWrapped(true);
834 alignFrame.alignPanel.updateLayout();
835 SeqCanvas seqCanvas = testee.seqCanvas;
836 int labelWidth = (int) PA.getValue(seqCanvas, "labelWidthWest");
837 assertTrue(labelWidth > 0);
839 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
841 assertEquals(testee.findColumn(evt), -1);
844 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
846 assertEquals(testee.findColumn(evt), 0);
849 * x over right edge of last residue (including scale left)
851 int residuesWide = av.getRanges().getViewportWidth();
852 assertTrue(residuesWide > 0);
853 x = labelWidth + charWidth * residuesWide - 1;
854 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
856 assertEquals(testee.findColumn(evt), residuesWide - 1);
859 * x over scale right (beyond drawn columns) results in -1
861 av.setScaleRightWrapped(true);
862 alignFrame.alignPanel.updateLayout();
863 labelWidth = (int) PA.getValue(seqCanvas, "labelWidthEast");
864 assertTrue(labelWidth > 0);
865 int residuesWide2 = av.getRanges().getViewportWidth();
866 assertTrue(residuesWide2 > 0);
867 assertTrue(residuesWide2 < residuesWide); // available width reduced
868 x += 1; // just over left edge of scale right
869 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
871 assertEquals(testee.findColumn(evt), -1);
873 // todo add startRes offset, hidden columns
877 @BeforeClass(alwaysRun = true)
878 public static void setUpBeforeClass() throws Exception
881 * use read-only test properties file
883 Cache.loadProperties("test/jalview/io/testProps.jvprops");
884 Jalview.main(new String[] { "-nonews" });
888 * waits for Swing event dispatch queue to empty
890 synchronized void waitForSwing()
894 EventQueue.invokeAndWait(new Runnable()
901 } catch (InterruptedException | InvocationTargetException e)
907 @Test(groups = "Functional")
908 public void testFindMousePosition_wrapped_scales_longSequence()
910 Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false");
911 Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
912 Cache.applicationProperties.setProperty("FONT_SIZE", "14");
913 Cache.applicationProperties.setProperty("FONT_NAME", "SansSerif");
914 Cache.applicationProperties.setProperty("FONT_STYLE", "0");
915 // sequence of 50 bases, doubled 10 times, = 51200 bases
916 String dna = "ATGGCCATTGGGCCCAAATTTCCCAAAGGGTTTCCCTGAGGTCAGTCAGA";
917 for (int i = 0; i < 10; i++)
921 assertEquals(dna.length(), 51200);
922 AlignFrame alignFrame = new FileLoader()
923 .LoadFileWaitTillLoaded("dna "+dna, DataSourceType.PASTE);
924 SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
925 AlignViewport av = alignFrame.getViewport();
926 av.setScaleAboveWrapped(true);
927 av.setScaleLeftWrapped(true);
928 av.setScaleRightWrapped(true);
929 alignFrame.alignPanel.updateLayout();
934 } catch (InterruptedException e)
938 final int charHeight = av.getCharHeight();
939 final int charWidth = av.getCharWidth();
940 assertEquals(charHeight, 17);
941 assertEquals(charWidth, 12);
943 FontMetrics fm = testee.getFontMetrics(av.getFont());
944 int labelWidth = fm.stringWidth("00000") + charWidth;
945 assertEquals(labelWidth, 57); // 5 x 9 + charWidth
946 assertEquals(testee.seqCanvas.getLabelWidthWest(), labelWidth);
952 * mouse at top left of wrapped panel; there is a gap of 2 * charHeight
953 * above the alignment
955 MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0,
956 x, y, 0, 0, 0, false, 0);
957 MousePos pos = testee.findMousePosition(evt);
958 assertEquals(pos.column, -1); // over scale left, not an alignment column
959 assertEquals(pos.seqIndex, -1); // above sequences
960 assertEquals(pos.annotationIndex, -1);
963 * cursor over scale above first sequence
967 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
969 pos = testee.findMousePosition(evt);
970 assertEquals(pos.seqIndex, -1);
971 assertEquals(pos.column, 0);
972 assertEquals(pos.annotationIndex, -1);
975 * cursor over scale left of first sequence
979 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
981 pos = testee.findMousePosition(evt);
982 assertEquals(pos.seqIndex, 0);
983 assertEquals(pos.column, -1);
984 assertEquals(pos.annotationIndex, -1);
987 * cursor over start of first sequence
990 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
992 pos = testee.findMousePosition(evt);
993 assertEquals(pos.seqIndex, 0);
994 assertEquals(pos.column, 0);
995 assertEquals(pos.annotationIndex, -1);
998 * move one character right, to bottom pixel of same row
1001 y += charHeight - 1;
1002 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
1004 pos = testee.findMousePosition(evt);
1005 assertEquals(pos.seqIndex, 0);
1006 assertEquals(pos.column, 1);
1009 * move down one pixel - now in the no man's land between rows
1012 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
1014 pos = testee.findMousePosition(evt);
1015 assertEquals(pos.seqIndex, -1);
1016 assertEquals(pos.column, 1);
1019 * move down two char heights less one pixel - still in the no man's land
1020 * (scale above + spacer line)
1022 y += (2 * charHeight - 1);
1023 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
1025 pos = testee.findMousePosition(evt);
1026 assertEquals(pos.seqIndex, -1);
1027 assertEquals(pos.column, 1);
1030 * move down one more pixel - now on the next row of the sequence
1033 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
1035 pos = testee.findMousePosition(evt);
1036 assertEquals(pos.seqIndex, 0);
1037 assertEquals(pos.column, 1 + av.getWrappedWidth());
1040 * scroll to near the end of the sequence
1042 SearchResultsI sr = new SearchResults();
1043 int scrollTo = dna.length() - 1000;
1044 sr.addResult(av.getAlignment().getSequenceAt(0), scrollTo, scrollTo);
1045 alignFrame.alignPanel.scrollToPosition(sr);
1048 * place the mouse on the first column of the 6th sequence, and
1049 * verify that (computed) findMousePosition matches (actual) ViewportRanges
1052 y = 17 * charHeight; // 17 = 6 times two header rows and 5 sequence rows
1053 evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0,
1055 pos = testee.findMousePosition(evt);
1056 assertEquals(pos.seqIndex, 0);
1057 int expected = av.getRanges().getStartRes() + 5 * av.getWrappedWidth();
1058 assertEquals(pos.column, expected);