d2344cc8f77ffa21dbcc83ae0d66b8bd645e56a2
[jalview.git] / test / jalview / gui / SeqPanelTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
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.
11  *  
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.
16  * 
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.
20  */
21 package jalview.gui;
22
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertTrue;
25
26 import jalview.api.AlignViewportI;
27 import jalview.bin.Cache;
28 import jalview.bin.Jalview;
29 import jalview.datamodel.Alignment;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.Sequence;
32 import jalview.datamodel.SequenceI;
33 import jalview.gui.SeqPanel.MousePos;
34 import jalview.io.DataSourceType;
35 import jalview.io.FileLoader;
36
37 import java.awt.Event;
38 import java.awt.event.MouseEvent;
39
40 import javax.swing.JLabel;
41
42 import org.testng.annotations.AfterMethod;
43 import org.testng.annotations.BeforeClass;
44 import org.testng.annotations.Test;
45
46 import junit.extensions.PA;
47
48 public class SeqPanelTest
49 {
50   AlignFrame af;
51
52   @BeforeClass(alwaysRun = true)
53   public void setUpJvOptionPane()
54   {
55     JvOptionPane.setInteractiveMode(false);
56     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
57   }
58   @Test(groups = "Functional")
59   public void testSetStatusReturnsNearestResiduePosition()
60   {
61     SequenceI seq1 = new Sequence("Seq1", "AACDE");
62     SequenceI seq2 = new Sequence("Seq2", "AA--E");
63     AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
64     AlignFrame alignFrame = new AlignFrame(al, al.getWidth(),
65             al.getHeight());
66     AlignmentI visAl = alignFrame.getViewport().getAlignment();
67
68     // Test either side of gap
69     assertEquals(
70             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
71                     visAl.getSequenceAt(1), 1, 1), 2);
72     assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
73             "Sequence 2 ID: Seq2 Residue: ALA (2)");
74     assertEquals(
75             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
76                     visAl.getSequenceAt(1), 4, 1), 3);
77     assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
78             "Sequence 2 ID: Seq2 Residue: GLU (3)");
79     // no status message at a gap, returns next residue position to the right
80     assertEquals(
81             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
82                     visAl.getSequenceAt(1), 2, 1), 3);
83     assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
84             "Sequence 2 ID: Seq2");
85     assertEquals(
86             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
87                     visAl.getSequenceAt(1), 3, 1), 3);
88     assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
89             "Sequence 2 ID: Seq2");
90   }
91
92   @Test(groups = "Functional")
93   public void testAmbiguousAminoAcidGetsStatusMessage()
94   {
95     SequenceI seq1 = new Sequence("Seq1", "ABCDE");
96     SequenceI seq2 = new Sequence("Seq2", "AB--E");
97     AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
98     AlignFrame alignFrame = new AlignFrame(al, al.getWidth(),
99             al.getHeight());
100     AlignmentI visAl = alignFrame.getViewport().getAlignment();
101
102     assertEquals(
103             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
104                     visAl.getSequenceAt(1), 1, 1), 2);
105     assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
106             "Sequence 2 ID: Seq2 Residue: B (2)");
107   }
108
109   @Test(groups = "Functional")
110   public void testFindMousePosition_unwrapped()
111   {
112     String seqData = ">Seq1\nAACDE\n>Seq2\nAA--E\n";
113     AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(seqData,
114             DataSourceType.PASTE);
115     AlignViewportI av = alignFrame.getViewport();
116     av.setShowAnnotation(true);
117     av.setWrapAlignment(false);
118     final int charHeight = av.getCharHeight();
119     final int charWidth = av.getCharWidth();
120     // sanity checks:
121     assertTrue(charHeight > 0);
122     assertTrue(charWidth > 0);
123     assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
124
125     SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
126     int x = 0;
127     int y = 0;
128
129     /*
130      * mouse at top left of unwrapped panel
131      */
132     MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
133             0, 0, 0, false, 0);
134     MousePos pos = testee.findMousePosition(evt);
135     assertEquals(pos.column, 0);
136     assertEquals(pos.seqIndex, 0);
137     assertEquals(pos.annotationIndex, -1);
138   }
139
140   @AfterMethod(alwaysRun = true)
141   public void tearDown()
142   {
143     Desktop.instance.closeAll_actionPerformed(null);
144   }
145
146   @Test(groups = "Functional")
147   public void testFindMousePosition_wrapped_annotations()
148   {
149     Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "true");
150     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
151     AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
152             "examples/uniref50.fa", DataSourceType.FILE);
153     AlignViewportI av = alignFrame.getViewport();
154     av.setScaleAboveWrapped(false);
155     av.setScaleLeftWrapped(false);
156     av.setScaleRightWrapped(false);
157     alignFrame.alignPanel.paintAlignment(false, false);
158     waitForSwing(); // for Swing thread
159
160     final int charHeight = av.getCharHeight();
161     final int charWidth = av.getCharWidth();
162     final int alignmentHeight = av.getAlignment().getHeight();
163     
164     // sanity checks:
165     assertTrue(charHeight > 0);
166     assertTrue(charWidth > 0);
167     assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
168   
169     SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
170     int x = 0;
171     int y = 0;
172   
173     /*
174      * mouse at top left of wrapped panel; there is a gap of charHeight
175      * above the alignment
176      */
177     MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
178             0, 0, 0, false, 0);
179     MousePos pos = testee.findMousePosition(evt);
180     assertEquals(pos.column, 0);
181     assertEquals(pos.seqIndex, -1); // above sequences
182     assertEquals(pos.annotationIndex, -1);
183
184     /*
185      * cursor at bottom of gap above
186      */
187     y = charHeight - 1;
188     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
189             false, 0);
190     pos = testee.findMousePosition(evt);
191     assertEquals(pos.seqIndex, -1);
192     assertEquals(pos.annotationIndex, -1);
193
194     /*
195      * cursor over top of first sequence
196      */
197     y = charHeight;
198     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
199             false, 0);
200     pos = testee.findMousePosition(evt);
201     assertEquals(pos.seqIndex, 0);
202     assertEquals(pos.annotationIndex, -1);
203
204     /*
205      * cursor at bottom of first sequence
206      */
207     y = 2 * charHeight - 1;
208     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
209             false, 0);
210     pos = testee.findMousePosition(evt);
211     assertEquals(pos.seqIndex, 0);
212     assertEquals(pos.annotationIndex, -1);
213
214     /*
215      * cursor at top of second sequence
216      */
217     y = 2 * charHeight;
218     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
219             false, 0);
220     pos = testee.findMousePosition(evt);
221     assertEquals(pos.seqIndex, 1);
222     assertEquals(pos.annotationIndex, -1);
223
224     /*
225      * cursor at bottom of second sequence
226      */
227     y = 3 * charHeight - 1;
228     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
229             false, 0);
230     pos = testee.findMousePosition(evt);
231     assertEquals(pos.seqIndex, 1);
232     assertEquals(pos.annotationIndex, -1);
233
234     /*
235      * cursor at bottom of last sequence
236      */
237     y = charHeight * (1 + alignmentHeight) - 1;
238     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
239             false, 0);
240     pos = testee.findMousePosition(evt);
241     assertEquals(pos.seqIndex, alignmentHeight - 1);
242     assertEquals(pos.annotationIndex, -1);
243
244     /*
245      * cursor below sequences, in 3-pixel gap above annotations
246      * method reports index of nearest sequence above
247      */
248     y += 1;
249     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
250             false, 0);
251     pos = testee.findMousePosition(evt);
252     assertEquals(pos.seqIndex, alignmentHeight - 1);
253     assertEquals(pos.annotationIndex, -1);
254
255     /*
256      * cursor still in the gap above annotations, now at the bottom of it
257      */
258     y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
259     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
260             false, 0);
261     pos = testee.findMousePosition(evt);
262     assertEquals(pos.seqIndex, alignmentHeight - 1);
263     assertEquals(pos.annotationIndex, -1);
264
265     /*
266      * cursor at the top of the first annotation  
267      */
268     y += 1;
269     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
270             false, 0);
271     pos = testee.findMousePosition(evt);
272     assertEquals(pos.seqIndex, alignmentHeight - 1);
273     assertEquals(pos.annotationIndex, 0); // over first annotation
274
275     /*
276      * cursor at the bottom of the first annotation  
277      */
278     y += av.getAlignment().getAlignmentAnnotation()[0].height - 1;
279     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
280             false, 0);
281     pos = testee.findMousePosition(evt);
282     assertEquals(pos.seqIndex, alignmentHeight - 1);
283     assertEquals(pos.annotationIndex, 0);
284
285     /*
286      * cursor at the top of the second annotation  
287      */
288     y += 1;
289     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
290             false, 0);
291     pos = testee.findMousePosition(evt);
292     assertEquals(pos.seqIndex, alignmentHeight - 1);
293     assertEquals(pos.annotationIndex, 1);
294
295     /*
296      * cursor at the bottom of the second annotation  
297      */
298     y += av.getAlignment().getAlignmentAnnotation()[1].height - 1;
299     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
300             false, 0);
301     pos = testee.findMousePosition(evt);
302     assertEquals(pos.seqIndex, alignmentHeight - 1);
303     assertEquals(pos.annotationIndex, 1);
304
305     /*
306      * cursor at the top of the third annotation  
307      */
308     y += 1;
309     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
310             false, 0);
311     pos = testee.findMousePosition(evt);
312     assertEquals(pos.seqIndex, alignmentHeight - 1);
313     assertEquals(pos.annotationIndex, 2);
314
315     /*
316      * cursor at the bottom of the third annotation  
317      */
318     y += av.getAlignment().getAlignmentAnnotation()[2].height - 1;
319     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
320             false, 0);
321     pos = testee.findMousePosition(evt);
322     assertEquals(pos.seqIndex, alignmentHeight - 1);
323     assertEquals(pos.annotationIndex, 2);
324
325     /*
326      * cursor in gap between wrapped widths  
327      */
328     y += 1;
329     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
330             false, 0);
331     pos = testee.findMousePosition(evt);
332     assertEquals(pos.seqIndex, -1);
333     assertEquals(pos.annotationIndex, -1);
334
335     /*
336      * cursor at bottom of gap between wrapped widths  
337      */
338     y += charHeight - 1;
339     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
340             false, 0);
341     pos = testee.findMousePosition(evt);
342     assertEquals(pos.seqIndex, -1);
343     assertEquals(pos.annotationIndex, -1);
344
345     /*
346      * cursor at top of first sequence, second wrapped width  
347      */
348     y += 1;
349     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
350             false, 0);
351     pos = testee.findMousePosition(evt);
352     assertEquals(pos.seqIndex, 0);
353     assertEquals(pos.annotationIndex, -1);
354   }
355
356   @Test(groups = "Functional")
357   public void testFindMousePosition_wrapped_scaleAbove()
358   {
359     Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "true");
360     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
361     AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
362             "examples/uniref50.fa", DataSourceType.FILE);
363     AlignViewportI av = alignFrame.getViewport();
364     av.setScaleAboveWrapped(true);
365     av.setScaleLeftWrapped(false);
366     av.setScaleRightWrapped(false);
367     alignFrame.alignPanel.paintAlignment(false, false);
368     waitForSwing();
369
370     final int charHeight = av.getCharHeight();
371     final int charWidth = av.getCharWidth();
372     final int alignmentHeight = av.getAlignment().getHeight();
373     
374     // sanity checks:
375     assertTrue(charHeight > 0);
376     assertTrue(charWidth > 0);
377     assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
378   
379     SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
380     int x = 0;
381     int y = 0;
382   
383     /*
384      * mouse at top left of wrapped panel; there is a gap of charHeight
385      * above the alignment
386      */
387     MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
388             0, 0, 0, false, 0);
389     MousePos pos = testee.findMousePosition(evt);
390     assertEquals(pos.column, 0);
391     assertEquals(pos.seqIndex, -1); // above sequences
392     assertEquals(pos.annotationIndex, -1);
393   
394     /*
395      * cursor at bottom of gap above
396      * two charHeights including scale panel
397      */
398     y = 2 * charHeight - 1;
399     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
400             false, 0);
401     pos = testee.findMousePosition(evt);
402     assertEquals(pos.seqIndex, -1);
403     assertEquals(pos.annotationIndex, -1);
404   
405     /*
406      * cursor over top of first sequence
407      */
408     y += 1;
409     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
410             false, 0);
411     pos = testee.findMousePosition(evt);
412     assertEquals(pos.seqIndex, 0);
413     assertEquals(pos.annotationIndex, -1);
414   
415     /*
416      * cursor at bottom of first sequence
417      */
418     y += charHeight - 1;
419     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
420             false, 0);
421     pos = testee.findMousePosition(evt);
422     assertEquals(pos.seqIndex, 0);
423     assertEquals(pos.annotationIndex, -1);
424   
425     /*
426      * cursor at top of second sequence
427      */
428     y += 1;
429     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
430             false, 0);
431     pos = testee.findMousePosition(evt);
432     assertEquals(pos.seqIndex, 1);
433     assertEquals(pos.annotationIndex, -1);
434   
435     /*
436      * cursor at bottom of second sequence
437      */
438     y += charHeight - 1;
439     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
440             false, 0);
441     pos = testee.findMousePosition(evt);
442     assertEquals(pos.seqIndex, 1);
443     assertEquals(pos.annotationIndex, -1);
444   
445     /*
446      * cursor at bottom of last sequence
447      * (scale + gap + sequences)
448      */
449     y = charHeight * (2 + alignmentHeight) - 1;
450     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
451             false, 0);
452     pos = testee.findMousePosition(evt);
453     assertEquals(pos.seqIndex, alignmentHeight - 1);
454     assertEquals(pos.annotationIndex, -1);
455   
456     /*
457      * cursor below sequences, in 3-pixel gap above annotations
458      */
459     y += 1;
460     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
461             false, 0);
462     pos = testee.findMousePosition(evt);
463     assertEquals(pos.seqIndex, alignmentHeight - 1);
464     assertEquals(pos.annotationIndex, -1);
465   
466     /*
467      * cursor still in the gap above annotations, now at the bottom of it
468      * method reports index of nearest sequence above  
469      */
470     y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
471     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
472             false, 0);
473     pos = testee.findMousePosition(evt);
474     assertEquals(pos.seqIndex, alignmentHeight - 1);
475     assertEquals(pos.annotationIndex, -1);
476   
477     /*
478      * cursor at the top of the first annotation  
479      */
480     y += 1;
481     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
482             false, 0);
483     pos = testee.findMousePosition(evt);
484     assertEquals(pos.seqIndex, alignmentHeight - 1);
485     assertEquals(pos.annotationIndex, 0); // over first annotation
486   
487     /*
488      * cursor at the bottom of the first annotation  
489      */
490     y += av.getAlignment().getAlignmentAnnotation()[0].height - 1;
491     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
492             false, 0);
493     pos = testee.findMousePosition(evt);
494     assertEquals(pos.seqIndex, alignmentHeight - 1);
495     assertEquals(pos.annotationIndex, 0);
496   
497     /*
498      * cursor at the top of the second annotation  
499      */
500     y += 1;
501     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
502             false, 0);
503     pos = testee.findMousePosition(evt);
504     assertEquals(pos.seqIndex, alignmentHeight - 1);
505     assertEquals(pos.annotationIndex, 1);
506   
507     /*
508      * cursor at the bottom of the second annotation  
509      */
510     y += av.getAlignment().getAlignmentAnnotation()[1].height - 1;
511     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
512             false, 0);
513     pos = testee.findMousePosition(evt);
514     assertEquals(pos.seqIndex, alignmentHeight - 1);
515     assertEquals(pos.annotationIndex, 1);
516   
517     /*
518      * cursor at the top of the third annotation  
519      */
520     y += 1;
521     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
522             false, 0);
523     pos = testee.findMousePosition(evt);
524     assertEquals(pos.seqIndex, alignmentHeight - 1);
525     assertEquals(pos.annotationIndex, 2);
526   
527     /*
528      * cursor at the bottom of the third annotation  
529      */
530     y += av.getAlignment().getAlignmentAnnotation()[2].height - 1;
531     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
532             false, 0);
533     pos = testee.findMousePosition(evt);
534     assertEquals(pos.seqIndex, alignmentHeight - 1);
535     assertEquals(pos.annotationIndex, 2);
536   
537     /*
538      * cursor in gap between wrapped widths  
539      */
540     y += 1;
541     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
542             false, 0);
543     pos = testee.findMousePosition(evt);
544     assertEquals(pos.seqIndex, -1);
545     assertEquals(pos.annotationIndex, -1);
546   
547     /*
548      * cursor at bottom of gap between wrapped widths  
549      */
550     y += charHeight - 1;
551     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
552             false, 0);
553     pos = testee.findMousePosition(evt);
554     assertEquals(pos.seqIndex, -1);
555     assertEquals(pos.annotationIndex, -1);
556   
557     /*
558      * cursor at top of scale, second wrapped width  
559      */
560     y += 1;
561     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
562             false, 0);
563     pos = testee.findMousePosition(evt);
564     assertEquals(pos.seqIndex, -1);
565     assertEquals(pos.annotationIndex, -1);
566
567     /*
568      * cursor at bottom of scale, second wrapped width  
569      */
570     y += charHeight - 1;
571     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
572             false, 0);
573     pos = testee.findMousePosition(evt);
574     assertEquals(pos.seqIndex, -1);
575     assertEquals(pos.annotationIndex, -1);
576
577     /*
578      * cursor at top of first sequence, second wrapped width  
579      */
580     y += 1;
581     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
582             false, 0);
583     pos = testee.findMousePosition(evt);
584     assertEquals(pos.seqIndex, 0);
585     assertEquals(pos.annotationIndex, -1);
586   }
587
588   @Test(groups = "Functional")
589   public void testFindMousePosition_wrapped_noAnnotations()
590   {
591     Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false");
592     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
593     AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
594             "examples/uniref50.fa", DataSourceType.FILE);
595     AlignViewportI av = alignFrame.getViewport();
596     av.setScaleAboveWrapped(false);
597     av.setScaleLeftWrapped(false);
598     av.setScaleRightWrapped(false);
599     alignFrame.alignPanel.paintAlignment(false, false);
600     waitForSwing();
601
602     final int charHeight = av.getCharHeight();
603     final int charWidth = av.getCharWidth();
604     final int alignmentHeight = av.getAlignment().getHeight();
605     
606     // sanity checks:
607     assertTrue(charHeight > 0);
608     assertTrue(charWidth > 0);
609     assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
610   
611     SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
612     int x = 0;
613     int y = 0;
614   
615     /*
616      * mouse at top left of wrapped panel; there is a gap of charHeight
617      * above the alignment
618      */
619     MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
620             0, 0, 0, false, 0);
621     MousePos pos = testee.findMousePosition(evt);
622     assertEquals(pos.column, 0);
623     assertEquals(pos.seqIndex, -1); // above sequences
624     assertEquals(pos.annotationIndex, -1);
625   
626     /*
627      * cursor over top of first sequence
628      */
629     y = charHeight;
630     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
631             false, 0);
632     pos = testee.findMousePosition(evt);
633     assertEquals(pos.seqIndex, 0);
634     assertEquals(pos.annotationIndex, -1);
635
636     /*
637      * cursor at bottom of last sequence
638      */
639     y = charHeight * (1 + alignmentHeight) - 1;
640     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
641             false, 0);
642     pos = testee.findMousePosition(evt);
643     assertEquals(pos.seqIndex, alignmentHeight - 1);
644     assertEquals(pos.annotationIndex, -1);
645   
646     /*
647      * cursor below sequences, at top of charHeight gap between widths
648      */
649     y += 1;
650     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
651             false, 0);
652     pos = testee.findMousePosition(evt);
653     assertEquals(pos.seqIndex, -1);
654     assertEquals(pos.annotationIndex, -1);
655   
656     /*
657      * cursor below sequences, at top of charHeight gap between widths
658      */
659     y += charHeight - 1;
660     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
661             false, 0);
662     pos = testee.findMousePosition(evt);
663     assertEquals(pos.seqIndex, -1);
664     assertEquals(pos.annotationIndex, -1);
665   
666     /*
667      * cursor at the top of the first sequence, second width  
668      */
669     y += 1;
670     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
671             false, 0);
672     pos = testee.findMousePosition(evt);
673     assertEquals(pos.seqIndex, 0);
674     assertEquals(pos.annotationIndex, -1);
675   }
676
677   @Test(groups = "Functional")
678   public void testFindColumn_unwrapped()
679   {
680     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "false");
681     AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
682             "examples/uniref50.fa", DataSourceType.FILE);
683     SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
684     int x = 0;
685     final int charWidth = alignFrame.getViewport().getCharWidth();
686     assertTrue(charWidth > 0); // sanity check
687     assertEquals(alignFrame.getViewport().getRanges().getStartRes(), 0);
688
689     /*
690      * mouse at top left of unwrapped panel
691      */
692     MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
693             0, 0, 0, false, 0);
694     assertEquals(testee.findColumn(evt), 0);
695     
696     /*
697      * not quite one charWidth across
698      */
699     x = charWidth-1;
700     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
701             0, 0, 0, false, 0);
702     assertEquals(testee.findColumn(evt), 0);
703
704     /*
705      * one charWidth across
706      */
707     x = charWidth;
708     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
709             false, 0);
710     assertEquals(testee.findColumn(evt), 1);
711
712     /*
713      * two charWidths across
714      */
715     x = 2 * charWidth;
716     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
717             false, 0);
718     assertEquals(testee.findColumn(evt), 2);
719
720     /*
721      * limited to last column of seqcanvas
722      */
723     x = 20000;
724     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
725             false, 0);
726     SeqCanvas seqCanvas = alignFrame.alignPanel.getSeqPanel().seqCanvas;
727     int w = seqCanvas.getWidth();
728     // limited to number of whole columns, base 0
729     int expected = w / charWidth - 1;
730     assertEquals(testee.findColumn(evt), expected);
731
732     /*
733      * hide columns 5-10 (base 1)
734      */
735     alignFrame.getViewport().hideColumns(4, 9);
736     x = 5 * charWidth + 2;
737     // x is in 6th visible column, absolute column 12, or 11 base 0
738     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
739             false, 0);
740     assertEquals(testee.findColumn(evt), 11);
741   }
742
743   @Test(groups = "Functional")
744   public void testFindColumn_wrapped()
745   {
746     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
747     AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
748             "examples/uniref50.fa", DataSourceType.FILE);
749     AlignViewport av = alignFrame.getViewport();
750     av.setScaleAboveWrapped(false);
751     av.setScaleLeftWrapped(false);
752     av.setScaleRightWrapped(false);
753     alignFrame.alignPanel.paintAlignment(false, false);
754     // need to wait for repaint to finish!
755     waitForSwing();
756     SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
757     int x = 0;
758     final int charWidth = av.getCharWidth();
759     assertTrue(charWidth > 0); // sanity check
760     assertEquals(av.getRanges().getStartRes(), 0);
761   
762     /*
763      * mouse at top left of wrapped panel, no West (left) scale
764      */
765     MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
766             0, 0, 0, false, 0);
767     assertEquals(testee.findColumn(evt), 0);
768     
769     /*
770      * not quite one charWidth across
771      */
772     x = charWidth-1;
773     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
774             0, 0, 0, false, 0);
775     assertEquals(testee.findColumn(evt), 0);
776   
777     /*
778      * one charWidth across
779      */
780     x = charWidth;
781     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
782             false, 0);
783     assertEquals(testee.findColumn(evt), 1);
784
785     /*
786      * x over scale left (before drawn columns) results in -1
787      */
788     av.setScaleLeftWrapped(true);
789     alignFrame.alignPanel.paintAlignment(false, false);
790     waitForSwing();
791     SeqCanvas seqCanvas = testee.seqCanvas;
792     int labelWidth = (int) PA.getValue(seqCanvas, "labelWidthWest");
793     assertTrue(labelWidth > 0);
794     x = labelWidth - 1;
795     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
796             false, 0);
797     assertEquals(testee.findColumn(evt), -1);
798
799     x = labelWidth;
800     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
801             false, 0);
802     assertEquals(testee.findColumn(evt), 0);
803
804     /*
805      * x over right edge of last residue (including scale left)
806      */
807     int residuesWide = av.getRanges().getViewportWidth();
808     assertTrue(residuesWide > 0);
809     x = labelWidth + charWidth * residuesWide - 1;
810     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
811             false, 0);
812     assertEquals(testee.findColumn(evt), residuesWide - 1);
813
814     /*
815      * x over scale right (beyond drawn columns) results in -1
816      */
817     av.setScaleRightWrapped(true);
818     alignFrame.alignPanel.paintAlignment(false, false);
819     waitForSwing();
820     labelWidth = (int) PA.getValue(seqCanvas, "labelWidthEast");
821     assertTrue(labelWidth > 0);
822     int residuesWide2 = av.getRanges().getViewportWidth();
823     assertTrue(residuesWide2 > 0);
824     assertTrue(residuesWide2 < residuesWide); // available width reduced
825     x += 1; // just over left edge of scale right
826     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
827             false, 0);
828     assertEquals(testee.findColumn(evt), -1);
829     
830     // todo add startRes offset, hidden columns
831
832   }
833   @BeforeClass(alwaysRun = true)
834   public static void setUpBeforeClass() throws Exception
835   {
836     /*
837      * use read-only test properties file
838      */
839     Cache.loadProperties("test/jalview/io/testProps.jvprops");
840     Jalview.main(new String[] { "-nonews" });
841   }
842
843   /**
844    * waits a few ms for Swing to do something
845    */
846   synchronized void waitForSwing()
847   {
848     try
849     {
850       super.wait(10);
851     } catch (InterruptedException e)
852     {
853       e.printStackTrace();
854     }
855   }
856 }