JAL-2388 Removing sources of non-determinism in unit tests
[jalview.git] / test / jalview / viewmodel / OverviewDimensionsTest.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.viewmodel;
22
23 import static org.testng.Assert.assertEquals;
24
25 import jalview.bin.Cache;
26 import jalview.bin.Jalview;
27 import jalview.datamodel.Alignment;
28 import jalview.datamodel.Sequence;
29 import jalview.datamodel.SequenceGroup;
30 import jalview.datamodel.SequenceI;
31 import jalview.gui.AlignFrame;
32 import jalview.gui.AlignViewport;
33 import jalview.gui.Desktop;
34 import jalview.gui.JvOptionPane;
35 import jalview.io.DataSourceType;
36 import jalview.io.FileLoader;
37
38 import java.util.List;
39
40 import org.testng.annotations.AfterMethod;
41 import org.testng.annotations.BeforeClass;
42 import org.testng.annotations.BeforeMethod;
43 import org.testng.annotations.Test;
44
45 @Test(singleThreaded = true)
46 public class OverviewDimensionsTest {
47
48   boolean showConservationSetting;
49
50   SequenceI seq1 = new Sequence(
51           "Seq1",
52           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
53
54   SequenceI seq2 = new Sequence(
55           "Seq2",
56           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
57
58   SequenceI seq3 = new Sequence(
59           "Seq3",
60           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
61
62   SequenceI seq4 = new Sequence(
63           "Seq4",
64           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
65
66   SequenceI seq5 = new Sequence(
67           "Seq5",
68           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
69
70   AlignFrame af;
71   AlignViewport av;
72   OverviewDimensions od;
73
74   float scalew;
75   float scaleh;
76   int boxWidth;
77   int boxHeight;
78
79   int viewHeight;
80
81   @BeforeClass(alwaysRun = true)
82   public void setUpJvOptionPane()
83   {
84     JvOptionPane.setInteractiveMode(false);
85     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
86   }
87
88   @BeforeMethod(alwaysRun = true)
89   public void setUp()
90   {
91     Jalview.main(new String[] { "-nonews", "-props",
92         "test/jalview/testProps.jvprops" });
93
94     Cache.applicationProperties.setProperty("SHOW_IDENTITY",
95             Boolean.TRUE.toString());
96     af = new FileLoader().LoadFileWaitTillLoaded(
97             "examples/testdata/bigal.fa",
98             DataSourceType.FILE);
99
100     /*
101      * Wait for viewport to initialise
102      */
103     synchronized (this)
104     {
105       while (af.getViewport().getEndRes() == 0)
106       {
107         try
108         {
109           wait(50);
110         } catch (InterruptedException e)
111         {
112         }
113       }
114     }
115
116     /*
117      * wait for Consensus thread to complete
118      */
119     synchronized (this)
120     {
121       while (af.getViewport().getConsensusSeq() == null)
122       {
123         try
124         {
125           wait(50);
126         } catch (InterruptedException e)
127         {
128         }
129       }
130     }
131
132     // get cached setting for showConservation
133     // reset it in AfterClass!
134     showConservationSetting = Cache.getDefault("SHOW_CONSERVATION", true);
135     
136     av = af.getViewport();
137
138     if (av.isCalcInProgress())
139     {
140
141     }
142
143     od = new OverviewDimensions(av);
144
145     while (av.isCalcInProgress())
146     {
147       try
148       {
149         Thread.sleep(50);
150       } catch (InterruptedException e)
151       {
152         System.out.println("Hiding cols interruption");
153       }
154     }
155
156     // Initial box sizing - default path through code
157     od.setBoxPosition();
158
159     scalew = (float) od.getWidth()
160             / (av.getAlignment().getWidth() * av.getCharWidth());
161     scaleh = (float) od.getSequencesHeight()
162             / (av.getAlignment().getHeight() * av.getCharHeight());
163     boxWidth = Math.round((av.getEndRes() - av.getStartRes() + 1)
164             * av.getCharWidth() * scalew);
165     boxHeight = Math.round((av.getEndSeq() - av.getStartSeq())
166             * av.getCharHeight() * scaleh);
167
168     viewHeight = av.getEndSeq() - av.getStartSeq();
169
170     init();
171   }
172
173   private void init()
174   {
175     av.showAllHiddenColumns();
176     av.showAllHiddenSeqs();
177     av.setSelectionGroup(null);
178     // o/w hidden seqs retain selection group, causes problems later when hiding
179     // sequences
180
181     // wait for conservation calc to complete
182     while (av.isCalcInProgress())
183     {
184       try
185       {
186         Thread.sleep(50);
187       } catch (InterruptedException e)
188       {
189
190       }
191     }
192
193     mouseClick(od, 0, 0);
194     moveViewport(0, 0);
195   }
196
197   @AfterMethod(alwaysRun = true)
198   public void tearDown()
199   {
200     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
201             Boolean.toString(showConservationSetting));
202     Desktop.instance.closeAll_actionPerformed(null);
203   }
204
205   /**
206    * Test that the OverviewDimensions constructor sets width and height
207    * correctly
208    */
209   @Test(groups = { "Functional" })
210   public void testConstructor()
211   {
212     SequenceI seqa = new Sequence("Seq1", "ABC");
213     SequenceI seqb = new Sequence("Seq2", "ABC");
214     SequenceI seqc = new Sequence("Seq3", "ABC");
215     SequenceI seqd = new Sequence("Seq4", "ABC");
216     SequenceI seqe = new Sequence("Seq5",
217             "ABCABCABCABCABCABCABCABCBACBACBACBAC");
218
219     int defaultGraphHeight = 20;
220     int maxWidth = 400;
221     int minWidth = 120;
222     int maxSeqHeight = 300;
223     int minSeqHeight = 40;
224
225     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
226             Boolean.toString(true));
227
228     // test for alignment with width > height
229     SequenceI[] seqs1 = new SequenceI[] { seqa, seqb };
230     Alignment al1 = new Alignment(seqs1);
231     al1.setDataset(null);
232     AlignViewport av1 = new AlignViewport(al1);
233
234     OverviewDimensions od = new OverviewDimensions(av1);
235     int scaledHeight = 266;
236     assertEquals(od.getGraphHeight(), defaultGraphHeight);
237     assertEquals(od.getSequencesHeight(), scaledHeight);
238     assertEquals(od.getWidth(), maxWidth);
239     assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight);
240
241     // test for alignment with width < height
242     SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd };
243     Alignment al2 = new Alignment(seqs2);
244     al2.setDataset(null);
245     AlignViewport av2 = new AlignViewport(al2);
246
247     od = new OverviewDimensions(av2);
248     int scaledWidth = 300;
249     assertEquals(od.getGraphHeight(), defaultGraphHeight);
250     assertEquals(od.getSequencesHeight(), maxSeqHeight);
251     assertEquals(od.getWidth(), scaledWidth);
252     assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight);
253
254     // test for alignment with width > height and sequence height scaled below
255     // min value
256     SequenceI[] seqs3 = new SequenceI[] { seqe };
257     Alignment al3 = new Alignment(seqs3);
258     al3.setDataset(null);
259     AlignViewport av3 = new AlignViewport(al3);
260
261     od = new OverviewDimensions(av3);
262     assertEquals(od.getGraphHeight(), defaultGraphHeight);
263     assertEquals(od.getSequencesHeight(), minSeqHeight);
264     assertEquals(od.getWidth(), maxWidth);
265     assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight);
266
267     // test for alignment with width < height and width scaled below min value
268     SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa,
269         seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd };
270     Alignment al4 = new Alignment(seqs4);
271     al4.setDataset(null);
272     AlignViewport av4 = new AlignViewport(al4);
273
274     od = new OverviewDimensions(av4);
275     assertEquals(od.getGraphHeight(), defaultGraphHeight);
276     assertEquals(od.getSequencesHeight(), maxSeqHeight);
277     assertEquals(od.getWidth(), minWidth);
278     assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight);
279
280     // test for alignment where no conservation annotation is shown
281     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
282             Boolean.toString(false));
283
284     Alignment al5 = new Alignment(seqs4);
285     al5.setDataset(null);
286     AlignViewport av5 = new AlignViewport(al5);
287
288     od = new OverviewDimensions(av5);
289     assertEquals(od.getGraphHeight(), 0);
290     assertEquals(od.getSequencesHeight(), maxSeqHeight);
291     assertEquals(od.getWidth(), minWidth);
292     assertEquals(od.getHeight(), maxSeqHeight);
293   }
294
295   /**
296    * Test that validation after mouse adjustments to boxX and boxY sets box
297    * dimensions and scroll values correctly, when there are no hidden rows or
298    * columns.
299    * 
300    * The current implementation uses multiple transformations between coordinate
301    * systems which often involve casting to int, which causes values to be
302    * truncated. As a result we can lose accuracy. The tests below use
303    * approximate test values where appropriate.
304    */
305   @Test(groups = { "Functional" })
306   public void testSetBoxFromMouseClick()
307   {
308     od.setBoxPositionByMouse(0, 0);
309     assertEquals(od.getBoxX(), 0);
310     assertEquals(od.getBoxY(), 0);
311     assertEquals(od.getBoxWidth(), boxWidth);
312     assertEquals(od.getScrollCol(), 0);
313     assertEquals(od.getScrollRow(), 0);
314
315     // negative boxX value reset to 0
316     mouseClick(od, -5, 10);
317     assertEquals(od.getBoxX(), 0);
318     assertEquals(od.getBoxWidth(), boxWidth);
319     assertEquals(od.getBoxHeight(), boxHeight);
320     assertEquals(od.getScrollRow(),
321             Math.round(10 / scaleh / av.getCharHeight()));
322     assertEquals(od.getScrollCol(), 0);
323
324     // negative boxY value reset to 0
325     mouseClick(od, 6, -2);
326     assertEquals(od.getBoxY(), 0);
327     assertEquals(od.getBoxWidth(), boxWidth);
328     assertEquals(od.getBoxHeight(), boxHeight);
329     assertEquals(od.getScrollCol(),
330             Math.round(6 / scalew / av.getCharWidth()));
331     assertEquals(od.getScrollRow(), 0);
332
333     // overly large boxX value reset to width-boxWidth
334     mouseClick(od, 100, 6);
335     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth(), 1.5);
336     assertEquals(od.getBoxY(), 6, 1.5);
337     assertEquals(od.getBoxWidth(), boxWidth);
338     assertEquals(od.getBoxHeight(), boxHeight);
339     assertEquals(od.getScrollCol(),
340             (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
341     assertEquals(od.getScrollRow(),
342             (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
343
344     // overly large boxY value reset to sequenceHeight - boxHeight
345     mouseClick(od, 10, 520);
346     assertEquals(od.getBoxX(), 10, 1.5);
347     assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight(),
348             1.5);
349     assertEquals(od.getBoxWidth(), boxWidth);
350     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
351     assertEquals(od.getScrollCol(),
352             (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
353     assertEquals(od.getScrollRow(),
354             (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
355
356     // click past end of alignment, as above
357     mouseClick(od, 3000, 5);
358     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth(), 1.5);
359     assertEquals(od.getBoxWidth(), boxWidth);
360     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
361     assertEquals(od.getScrollCol(),
362             (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
363     assertEquals(od.getScrollRow(),
364             (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
365
366     // move viewport so startRes non-zero and then mouseclick
367     moveViewportH(50);
368
369     // click at viewport position
370     int oldboxx = od.getBoxX();
371     int oldboxy = od.getBoxY();
372     mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2);
373     assertEquals(od.getBoxX(), oldboxx + 5, 1.5);
374     assertEquals(od.getBoxWidth(), boxWidth);
375     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
376     assertEquals(od.getScrollCol(),
377             (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
378     assertEquals(od.getBoxY(), oldboxy + 2, 1.5);
379     assertEquals(od.getScrollRow(),
380             (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
381
382     // click at top corner
383     mouseClick(od, 0, 0);
384     assertEquals(od.getBoxX(), 0);
385     assertEquals(od.getScrollCol(), 0);
386     assertEquals(od.getBoxY(), 0);
387     assertEquals(od.getScrollRow(), 0);
388     assertEquals(od.getBoxWidth(), boxWidth);
389     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
390   }
391
392   /**
393    * Test setting of the box position, when there are hidden cols at the start
394    * of the alignment
395    */
396   @Test(groups = { "Functional" })
397   public void testFromMouseWithHiddenColsAtStart()
398   {
399     od.setBoxPositionByMouse(0, 0);
400     assertEquals(od.getBoxX(), 0);
401     assertEquals(od.getBoxY(), 0);
402     assertEquals(od.getBoxWidth(), boxWidth);
403     assertEquals(od.getScrollCol(), 0);
404     assertEquals(od.getScrollRow(), 0);
405
406     // hide cols at start and check updated box position is correct
407     // changes boxX but not boxwidth
408     int lastHiddenCol = 30;
409     hideColumns(0, lastHiddenCol);
410
411     od.setBoxPosition();
412     assertEquals(od.getBoxX(),
413             Math.round((lastHiddenCol + 1) * scalew * av.getCharWidth()));
414     assertEquals(od.getBoxWidth(), boxWidth);
415     assertEquals(od.getBoxHeight(), boxHeight);
416
417     // try to click in hidden cols, check box does not move
418     // this test currently fails as the overview box does not behave like this!
419     /*    int xpos = 10;
420         mouseClick(od, xpos, 0);
421         assertEquals(od.getBoxX(),
422                 Math.round ((lastHiddenCol + 1) * scalew * av.getCharWidth()));
423         assertEquals(od.getBoxY(), 0);
424         assertEquals(od.getBoxWidth(), boxWidth);
425         assertEquals(od.getBoxHeight(), boxHeight);
426         assertEquals(od.getScrollRow(), 0);
427         assertEquals(od.getScrollCol(),
428                 Math.round (xpos / scalew / av.getCharWidth()));
429     */
430     // click to right of hidden columns, box moves to click point
431     testBoxIsAtClickPoint(40, 0);
432     assertEquals(od.getScrollRow(), 0);
433     assertEquals(od.getScrollCol(),
434             Math.round(40 / scalew / av.getCharWidth())
435  - lastHiddenCol,
436             1.5);
437
438     // click to right of hidden columns such that box runs over right hand side
439     // of alignment
440     // box position is adjusted away from the edge
441     // overly large boxX value reset to width-boxWidth
442     int xpos = 100;
443     mouseClick(od, xpos, 5);
444     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth(), 1.5);
445     assertEquals(od.getBoxY(), 5);
446     assertEquals(od.getBoxWidth(), boxWidth);
447     assertEquals(od.getBoxHeight(), boxHeight);
448     assertEquals(od.getScrollCol(),
449             Math.round(od.getBoxX() / scalew / av.getCharWidth())
450                     - lastHiddenCol, 1.5);
451     assertEquals(od.getScrollRow(),
452             Math.round(od.getBoxY() / scaleh / av.getCharHeight()));
453
454   }
455
456   /**
457    * Test setting of the box position, when there are hidden cols in the middle
458    * of the alignment
459    */
460   @Test(groups = { "Functional" })
461   public void testFromMouseWithHiddenColsInMiddle()
462   {
463     od.setBoxPositionByMouse(0, 0);
464     assertEquals(od.getBoxX(), 0);
465     assertEquals(od.getBoxY(), 0);
466     assertEquals(od.getBoxWidth(), boxWidth);
467     assertEquals(od.getScrollCol(), 0);
468     assertEquals(od.getScrollRow(), 0);
469     
470     // hide columns 60-68, no change to box position or dimensions
471     int firstHidden = 60;
472     int lastHidden = 68;
473     hideColumns(firstHidden, lastHidden);
474
475     od.setBoxPosition();
476     assertEquals(od.getBoxX(), 0);
477     assertEquals(od.getBoxY(), 0);
478     assertEquals(od.getBoxWidth(), boxWidth);
479     assertEquals(od.getScrollCol(), 0);
480     assertEquals(od.getScrollRow(), 0);
481     
482     // move box so that it overlaps with hidden cols on one side
483     // box width changes, boxX and scrollCol as for unhidden case
484     int xpos = 50 - boxWidth; // 50 is position in overview halfway between cols
485                               // 60 and 70
486     mouseClick(od, xpos, 0);
487     assertEquals(od.getBoxX(), xpos);
488     assertEquals(od.getBoxY(), 0);
489     assertEquals(
490             od.getBoxWidth(),
491             Math.round(boxWidth + (lastHidden - firstHidden + 1) * scalew
492                     * av.getCharWidth()));
493     assertEquals(od.getBoxHeight(), boxHeight);
494     assertEquals(od.getScrollCol(),
495             Math.round(xpos / scalew / av.getCharWidth()));
496     assertEquals(od.getScrollRow(), 0);
497
498     // move box so that it completely covers hidden cols
499     // box width changes, boxX and scrollCol as for hidden case
500     xpos = 30;
501     mouseClick(od, xpos, 0);
502     assertEquals(od.getBoxX(), xpos);
503     assertEquals(od.getBoxY(), 0);
504     assertEquals(
505             od.getBoxWidth(),
506             Math.round(boxWidth + (lastHidden - firstHidden + 1) * scalew
507                     * av.getCharWidth()));
508     assertEquals(od.getBoxHeight(), boxHeight);
509     assertEquals(od.getScrollCol(),
510             Math.round(xpos / scalew / av.getCharWidth()), 1.5);
511     assertEquals(od.getScrollRow(), 0);
512
513     // move box so boxX is in hidden cols, box overhangs at right
514     // box width back to normal, boxX and scrollCol move to right of hidden area
515     // TODO currently this test fails in the Jalview GUI, there is a gap between
516     // the rhs of the hidden area and the box
517     /*    xpos = 50;
518         mouseClick(od, xpos, 0);
519         assertEquals(od.getBoxX(),
520                 (lastHidden + 1) * scalew * av.getCharWidth(), 1.5);
521         assertEquals(od.getBoxY(), 0);
522         assertEquals(od.getBoxWidth(), boxWidth, 1.5);
523         assertEquals(od.getBoxHeight(), boxHeight);
524         assertEquals(od.getScrollCol(),
525                 Math.round(xpos / scalew / av.getCharWidth()), 1.5);
526         assertEquals(od.getScrollRow(), 0);*/
527
528     // move box so boxX is to right of hidden cols, but does not go beyond full
529     // width of alignment
530     // box width, boxX and scrollCol all as for non-hidden case
531     // TODO currently this test fails in the Jalview GUI because boxX is
532     // calculated
533     // based on the current boxWidth, which includes hidden columns, thereby
534     // pushing
535     // the box off the end of the alignment. So boxX is adjusted backwards
536     // unnecessarily.
537     /*   xpos = 72;
538        testBoxIsAtClickPoint(xpos, 0);
539        assertEquals(od.getScrollRow(), 0);
540        assertEquals(od.getScrollCol(),
541                Math.round(xpos / scalew / av.getCharWidth())
542                - lastHidden, 1.5);*/
543     
544     // move box so it goes beyond full width of alignment
545     // boxX, scrollCol adjusted back, box width normal
546     xpos = 3000;
547     mouseClick(od, xpos, 5);
548     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth(), 1.5);
549     assertEquals(od.getBoxY(), 5);
550     assertEquals(od.getBoxWidth(), boxWidth);
551     assertEquals(od.getBoxHeight(), boxHeight);
552     assertEquals(od.getScrollCol(),
553             Math.round((od.getBoxX() / scalew / av.getCharWidth())
554                     - (lastHidden - firstHidden + 1)));
555     assertEquals(od.getScrollRow(),
556             Math.round(od.getBoxY() / scaleh / av.getCharHeight()));
557
558   }
559
560   /**
561    * Test setting of the box position, when there are hidden cols at the end of
562    * the alignment
563    */
564   @Test(groups = { "Functional" })
565   public void testFromMouseWithHiddenColsAtEnd()
566   {
567     od.setBoxPositionByMouse(0, 0);
568     assertEquals(od.getBoxX(), 0);
569     assertEquals(od.getBoxY(), 0);
570     assertEquals(od.getBoxWidth(), boxWidth);
571     assertEquals(od.getScrollCol(), 0);
572     assertEquals(od.getScrollRow(), 0);
573
574     // hide columns 140-157, no change to box position or dimensions
575     int firstHidden = 140;
576     int lastHidden = 157;
577     hideColumns(firstHidden, lastHidden);
578     od.setBoxPosition();
579     assertEquals(od.getBoxX(), 0);
580     assertEquals(od.getBoxY(), 0);
581     assertEquals(od.getBoxWidth(), boxWidth);
582     assertEquals(od.getScrollCol(), 0);
583     assertEquals(od.getScrollRow(), 0);
584
585     // click to left of hidden cols, without overlapping
586     // boxX, scrollCol and width as normal
587     int xpos = 5;
588     testBoxIsAtClickPoint(xpos, 0);
589     assertEquals(od.getScrollRow(), 0);
590     assertEquals(od.getScrollCol(),
591             Math.round(xpos / scalew / av.getCharWidth()), 1.5);
592
593     // click to left of hidden cols, with overlap
594     // boxX and scrollCol adjusted for hidden cols, width normal
595     // TODO this fails because setBoxPosition screws up the hidden cols calc
596     // only works in GUI because of AlignmentPanel::setScrollValues
597     /*xpos = 115 - boxWidth;
598     mouseClick(od, xpos, 0);
599     assertEquals(
600             od.getBoxX(),
601             Math.round((firstHidden - 1) * scalew * av.getCharWidth())
602                     - od.getBoxWidth(), 1.5);
603     assertEquals(od.getBoxY(), 0);
604     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
605     assertEquals(od.getBoxHeight(), boxHeight);
606     assertEquals(od.getScrollCol(),
607             Math.round(od.getBoxX() / scalew / av.getCharWidth()), 1.5);
608     assertEquals(od.getScrollRow(), 0);*/
609
610     // click in hidden cols
611     // boxX and scrollCol adjusted for hidden cols, width normal
612     // TODO breaks as above test
613     /*xpos = 115;
614     assertEquals(
615             od.getBoxX(),
616             Math.round((firstHidden - 1) * scalew * av.getCharWidth())
617                     - od.getBoxWidth(), 1.5);
618     assertEquals(od.getBoxY(), 0);
619     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
620     assertEquals(od.getBoxHeight(), boxHeight);
621     assertEquals(od.getScrollCol(),
622             Math.round(od.getBoxX() / scalew / av.getCharWidth()), 1.5);
623     assertEquals(od.getScrollRow(), 0);*/
624
625     // click off end of alignment
626     // boxX and scrollCol adjusted for hidden cols, width normal
627     // TODO breaks as above test
628     /*    xpos = 3000;
629         assertEquals(
630                 od.getBoxX(),
631                 Math.round((firstHidden - 1) * scalew * av.getCharWidth())
632                         - od.getBoxWidth(), 1.5);
633         assertEquals(od.getBoxY(), 0);
634         assertEquals(od.getBoxWidth(), boxWidth, 1.5);
635         assertEquals(od.getBoxHeight(), boxHeight);
636         assertEquals(od.getScrollCol(),
637                 Math.round(od.getBoxX() / scalew / av.getCharWidth()), 1.5);
638         assertEquals(od.getScrollRow(), 0);*/
639   }
640
641   /**
642    * Test that the box position is set correctly when set from the viewport,
643    * with no hidden rows or columns
644    */
645   @Test(groups = { "Functional" })
646   public void testSetBoxFromViewport()
647   {
648     // move viewport to start of alignment
649     moveViewport(0, 0);
650     assertEquals(od.getBoxX(), 0);
651     assertEquals(od.getBoxY(), 0);
652     assertEquals(od.getBoxWidth(), boxWidth);
653     assertEquals(od.getBoxHeight(), boxHeight);
654
655     // move viewport to right
656     moveViewportH(70);
657     assertEquals(od.getBoxX(), Math.round(70 * scalew * av.getCharWidth()));
658     assertEquals(od.getBoxY(), 0);
659     assertEquals(od.getBoxWidth(), boxWidth);
660     assertEquals(od.getBoxHeight(), boxHeight);
661
662     // move viewport down
663     moveViewportV(100);
664     assertEquals(od.getBoxX(), Math.round(70 * scalew * av.getCharWidth()));
665     assertEquals(od.getBoxY(),
666             Math.round(100 * scaleh * av.getCharHeight()));
667     assertEquals(od.getBoxWidth(), boxWidth);
668     assertEquals(od.getBoxHeight(), boxHeight);
669
670     // move viewport to bottom right
671     moveViewport(98, 508);
672     assertEquals(od.getBoxX(), Math.round(98 * scalew * av.getCharWidth()));
673     assertEquals(od.getBoxY(),
674             Math.round(508 * scaleh * av.getCharHeight()));
675     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
676     assertEquals(od.getBoxHeight(), boxHeight);
677   }
678
679   /**
680    * Test that the box position is set correctly when there are hidden columns
681    * at the start
682    */
683   @Test(groups = { "Functional" })
684   public void testSetBoxFromViewportHiddenColsAtStart()
685   {
686     int firstHidden = 0;
687     int lastHidden = 20;
688     hideColumns(firstHidden, lastHidden);
689
690     // move viewport to start of alignment
691     moveViewport(0, 0);
692     assertEquals(od.getBoxX(),
693             Math.round((lastHidden + 1) * scalew * av.getCharWidth()));
694     assertEquals(od.getBoxY(), 0);
695     assertEquals(od.getBoxWidth(), boxWidth);
696     assertEquals(od.getBoxHeight(), boxHeight);
697
698     // move viewport to end of alignment - need to make startRes by removing
699     // hidden cols because of how viewport/overview are implemented
700     moveViewport(98 - lastHidden - 1, 0);
701     assertEquals(od.getBoxX(), Math.round(98 * scalew * av.getCharWidth()));
702     assertEquals(od.getBoxY(), 0);
703     assertEquals(od.getBoxWidth(), boxWidth);
704     assertEquals(od.getBoxHeight(), boxHeight);
705   }
706
707   /**
708    * Test that the box position is set correctly when there are hidden columns
709    * in the middle
710    */
711   @Test(groups = { "Functional" })
712   public void testSetBoxFromViewportHiddenColsInMiddle()
713   {
714     int firstHidden = 65;
715     int lastHidden = 75;
716     hideColumns(firstHidden, lastHidden);
717
718     // move viewport before hidden columns
719     moveViewport(3, 0);
720
721     assertEquals(od.getBoxX(), Math.round(3 * scalew * av.getCharWidth()));
722     assertEquals(od.getBoxY(), 0);
723     System.out.println(od.getBoxWidth());
724     assertEquals(od.getBoxWidth(), boxWidth);
725     System.out.println(od.getBoxWidth());
726     assertEquals(od.getBoxHeight(), boxHeight);
727
728     // move viewport to left of hidden columns with overlap
729     moveViewport(10, 0);
730     assertEquals(od.getBoxX(), Math.round(10 * scalew * av.getCharWidth()));
731     assertEquals(od.getBoxY(), 0);
732     assertEquals(
733             od.getBoxWidth(),
734             boxWidth
735                     + Math.round((lastHidden - firstHidden + 1) * scalew
736                             * av.getCharWidth()));
737     assertEquals(od.getBoxHeight(), boxHeight);
738
739     // move viewport to straddle hidden columns
740     moveViewport(60, 0);
741     assertEquals(od.getBoxX(), Math.round(60 * scalew * av.getCharWidth()));
742     assertEquals(od.getBoxY(), 0);
743     assertEquals(
744             od.getBoxWidth(),
745             boxWidth
746                     + Math.round((lastHidden - firstHidden + 1) * scalew
747                             * av
748 .getCharWidth()));
749     assertEquals(od.getBoxHeight(), boxHeight);
750
751     // move viewport to right of hidden columns, no overlap
752     moveViewport(80 - (lastHidden - firstHidden + 1), 0);
753     assertEquals(od.getBoxX(), Math.round(80 * scalew * av.getCharWidth()));
754     assertEquals(od.getBoxY(), 0);
755     assertEquals(od.getBoxWidth(), boxWidth);
756     assertEquals(od.getBoxHeight(), boxHeight);
757
758   }
759
760   /**
761    * Test that the box position is set correctly when there are hidden columns
762    * at the end
763    */
764   @Test(groups = { "Functional" })
765   public void testSetBoxFromViewportHiddenColsAtEnd()
766   {
767     int firstHidden = 145;
768     int lastHidden = 157;
769     hideColumns(firstHidden, lastHidden);
770
771     // move viewport before hidden columns
772     moveViewport(3, 0);
773     assertEquals(od.getBoxX(), Math.round(3 * scalew * av.getCharWidth()),
774             1.5);
775     assertEquals(od.getBoxY(), 0);
776     assertEquals(od.getBoxWidth(), boxWidth);
777     assertEquals(od.getBoxHeight(), boxHeight);
778
779     // move viewport to hidden columns
780     // TODO boxwidth includes hidden in overview panel (why?)
781     moveViewport(98, 0);
782     assertEquals(od.getBoxX(), Math.round(98 * scalew * av.getCharWidth()),
783             1.5);
784     assertEquals(od.getBoxY(), 0);
785     assertEquals(
786             od.getBoxWidth(),
787             boxWidth
788                     + Math.round((lastHidden - firstHidden + 1) * scalew
789                             * av.getCharWidth()), 1.5);
790     assertEquals(od.getBoxHeight(), boxHeight);
791   }
792
793   /**
794    * Test that the box position is set correctly when there are hidden rows at
795    * the start
796    */
797   @Test(groups = { "Functional" })
798   public void testSetBoxFromViewportHiddenRowsAtStart()
799   {
800     int firstHidden = 0;
801     int lastHidden = 20;
802     hideSequences(firstHidden, lastHidden + 1, lastHidden + 1);
803
804     // move viewport to start of alignment:
805     // box moves to below hidden rows, height remains same
806     moveViewport(0, 0);
807     assertEquals(od.getBoxX(), 0);
808     assertEquals(od.getBoxY(),
809             Math.round((lastHidden + 1) * scaleh * av.getCharHeight()));
810     assertEquals(od.getBoxWidth(), boxWidth);
811     assertEquals(od.getBoxHeight(), boxHeight);
812
813     // move viewport to end of alignment, need to account for hidden rows
814     // because of how alignment panel/overview panel are implemented
815
816     // AlignViewport adjusts endSeq using Alignment height which excludes hidden
817     // rows if we happen to be at the bottom of the alignment
818     // od.setBoxPosition adjusts endSeq to include hidden rows
819     // od.checkValid adjusts scroll position to exclude hidden rows
820     // TODO this test fails because of the above!
821
822     /*    moveViewport(0, 525 - viewHeight - lastHidden - 1);
823         assertEquals(od.getBoxX(), 0);
824         assertEquals(od.getBoxY(),
825                 (525 - viewHeight) * scaleh
826                 * av.getCharHeight(), 1.5);
827         assertEquals(od.getBoxWidth(), boxWidth, 1.5);
828         assertEquals(od.getBoxHeight(), boxHeight, 1.5);*/
829   }
830
831   /**
832    * Test that the box position is set correctly when there are hidden rows in
833    * the middle
834    */
835   @Test(groups = { "Functional" })
836   public void testSetBoxFromViewportHiddenRowsInMiddle()
837   {
838     int firstHidden = 200;
839     int lastHidden = 210;
840     hideSequences(firstHidden, lastHidden + 1, lastHidden + 1);
841
842     // move viewport to start of alignment:
843     // box, height etc as in non-hidden case
844     // TODO fails with boxy=12 because that's what setBoxPosition sets it to!
845     /*moveViewport(0, 0);
846     assertEquals(od.getBoxX(), 0);
847     assertEquals(od.getBoxY(), 0);
848     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
849     assertEquals(od.getBoxHeight(), boxHeight, 1.5);*/
850
851     // move viewport to straddle hidden rows
852     // TODO also fails with boxY out by 12
853     /*moveViewport(0, 198);
854     assertEquals(od.getBoxX(), 0);
855     assertEquals(od.getBoxY(), Math.round (198 * scaleh * av.getCharHeight()),
856             1.5);
857     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
858     assertEquals(od.getBoxHeight(), boxHeight
859             + ((lastHidden - firstHidden) * scaleh * av.getCharHeight()),
860             1.5);*/
861   }
862
863   /**
864    * Test that the box position is set correctly when there are hidden rows at
865    * the bottom
866    */
867   @Test(groups = { "Functional" })
868   public void testSetBoxFromViewportHiddenRowsAtEnd()
869   {
870     int firstHidden = 500;
871     int lastHidden = 524;
872     hideSequences(firstHidden - 1, lastHidden, firstHidden - 1);
873
874     // move viewport to start of alignment:
875     // box, height etc as in non-hidden case
876     moveViewport(0, 0);
877     assertEquals(od.getBoxX(), 0);
878     assertEquals(od.getBoxY(), 0);
879     assertEquals(od.getBoxWidth(), boxWidth);
880     assertEquals(od.getBoxHeight(), boxHeight);
881
882     // move viewport to end of alignment
883     // TODO fails with wrong boxHeight who knows why
884     /*moveViewport(0, firstHidden - viewHeight - 1);
885         assertEquals(od.getBoxX(), 0);
886         assertEquals(od.getBoxY(),
887      Math.round ((firstHidden - viewHeight - 1)
888                 * scaleh * av.getCharHeight()), 1.5);
889         assertEquals(od.getBoxWidth(), boxWidth, 1.5);
890         assertEquals(
891                 od.getBoxHeight(),
892                 boxHeight
893                         + Math.round ((lastHidden - firstHidden + 1) * scaleh * av
894                                 .getCharHeight()), 1.5);*/
895
896   }
897
898   /**
899    * Test setting of the box position, when there are hidden rows at the start
900    * of the alignment
901    */
902   @Test(groups = { "Functional" })
903   public void testFromMouseWithHiddenRowsAtStart()
904   {
905     od.setBoxPositionByMouse(0, 0);
906     assertEquals(od.getBoxX(), 0);
907     assertEquals(od.getBoxY(), 0);
908     assertEquals(od.getBoxHeight(), boxHeight);
909     assertEquals(od.getBoxWidth(), boxWidth);
910     assertEquals(od.getScrollCol(), 0);
911     assertEquals(od.getScrollRow(), 0);
912
913     // hide rows at start and check updated box position is correct
914     // changes boxY but not boxheight
915     int lastHiddenRow = 30;
916     hideSequences(0, lastHiddenRow + 1, lastHiddenRow + 1);
917
918     od.setBoxPosition();
919     assertEquals(od.getBoxX(), 0);
920     assertEquals(od.getBoxY(),
921             Math.round((lastHiddenRow + 1) * scaleh * av.getCharHeight()));
922     assertEquals(od.getBoxWidth(), boxWidth);
923     assertEquals(od.getBoxHeight(), boxHeight);
924
925     // click in hidden rows
926     // TODO fails because boxHeight is 27 not 25 (possible rounding issue)
927     /*    mouseClick(od, 0, 0);
928         assertEquals(od.getBoxX(), 0);
929         assertEquals(od.getBoxY(), 0);
930         assertEquals(od.getBoxWidth(), boxWidth, 1.5);
931         assertEquals(od.getBoxHeight(), boxHeight
932                 + Math.round ((lastHiddenRow + 1) * scaleh * av.getCharHeight()),
933                 1.5);*/
934
935     // click below hidden rows
936     mouseClick(od, 0, 150);
937     assertEquals(od.getBoxX(), 0);
938     assertEquals(od.getBoxY(), 150, 1.5);
939     assertEquals(od.getBoxWidth(), boxWidth);
940     assertEquals(od.getBoxHeight(), boxHeight);
941   }
942
943   /**
944    * Test setting of the box position, when there are hidden rows at the middle
945    * of the alignment
946    */
947   @Test(groups = { "Functional" })
948   public void testFromMouseWithHiddenRowsInMiddle()
949   {
950     assertEquals(od.getBoxHeight(), 10);
951
952     od.setBoxPositionByMouse(0, 0);
953
954     assertEquals(od.getBoxHeight(), 10);
955
956     assertEquals(od.getBoxX(), 0);
957     assertEquals(od.getBoxY(), 0);
958     assertEquals(od.getBoxWidth(), boxWidth);
959     assertEquals(od.getBoxHeight(), boxHeight);
960     assertEquals(od.getScrollCol(), 0);
961     assertEquals(od.getScrollRow(), 0);
962
963     // hide rows in middle and check updated box position is correct
964     // no changes
965     int firstHiddenRow = 50;
966     int lastHiddenRow = 60;
967     assertEquals(od.getBoxHeight(), 10);
968     hideSequences(firstHiddenRow, lastHiddenRow + 1, lastHiddenRow + 1);
969     assertEquals(od.getBoxHeight(), 10);
970
971     od.setBoxPosition();
972     assertEquals(od.getBoxHeight(), 10);
973
974     assertEquals(od.getBoxX(), 0);
975     assertEquals(od.getBoxY(), 0);
976     assertEquals(od.getBoxWidth(), boxWidth);
977     assertEquals(od.getBoxHeight(), boxHeight);
978
979     // click above hidden rows, so that box overlaps
980     int ypos = 40;
981     // TODO test fails because box does not change height - dealt with by scroll
982     // values
983     /*    mouseClick(od, 0, Math.round (ypos / scaleh / av.getCharHeight()));
984         assertEquals(od.getBoxX(), 0);
985         assertEquals(od.getBoxY(), Math.round (ypos / scaleh / av.getCharHeight()),
986                 1.5);
987         assertEquals(od.getBoxWidth(), boxWidth, 1.5);
988         assertEquals(
989                 od.getBoxHeight(),
990                 boxHeight
991                         + Math.round ((lastHiddenRow - firstHiddenRow + 1) / scaleh / av
992                                 .getCharHeight()), 1.5);
993     */
994     // click so that box straddles hidden rows
995     ypos = 48;
996     // TODO test fails because box does not change height - dealt with by scroll
997     // values
998     /*mouseClick(od, 0, Math.round (ypos / scaleh / av.getCharHeight()));
999     assertEquals(od.getBoxX(), 0);
1000     assertEquals(od.getBoxY(), Math.round (ypos / scaleh / av.getCharHeight()),
1001             1.5);
1002     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
1003     assertEquals(
1004             od.getBoxHeight(),
1005             boxHeight
1006                     + Math.round ((lastHiddenRow - firstHiddenRow + 1) / scaleh / av
1007                             .getCharHeight()), 1.5);*/
1008   }
1009
1010   /**
1011    * Test setting of the box position, when there are hidden rows at the end of
1012    * the alignment
1013    */
1014   @Test(groups = { "Functional" })
1015   public void testFromMouseWithHiddenRowsAtEnd()
1016   {
1017     od.setBoxPositionByMouse(0, 0);
1018     assertEquals(od.getBoxX(), 0);
1019     assertEquals(od.getBoxY(), 0);
1020     assertEquals(od.getBoxWidth(), boxWidth);
1021     assertEquals(od.getBoxHeight(), boxHeight);
1022     assertEquals(od.getScrollCol(), 0);
1023     assertEquals(od.getScrollRow(), 0);
1024
1025     // hide rows at end and check updated box position is correct
1026     // no changes
1027     int firstHidden = 500;
1028     int lastHidden = 524;
1029     hideSequences(firstHidden - 1, lastHidden, firstHidden - 1);
1030
1031     od.setBoxPosition();
1032     assertEquals(od.getBoxX(), 0);
1033     assertEquals(od.getBoxY(), 0);
1034     assertEquals(od.getBoxWidth(), boxWidth);
1035     assertEquals(od.getBoxHeight(), boxHeight);
1036
1037     // click above hidden rows
1038     int ypos = 40; // row 40
1039     mouseClick(od, 0, Math.round(ypos * scaleh * av.getCharHeight()));
1040     assertEquals(od.getBoxX(), 0);
1041     assertEquals(od.getBoxY(),
1042             Math.round(ypos * scaleh * av.getCharHeight()));
1043     assertEquals(od.getBoxWidth(), boxWidth);
1044     assertEquals(od.getBoxHeight(), boxHeight);
1045
1046     // click above hidden rows so box overlaps
1047     // boxY moved upwards, boxHeight remains same
1048     // TODO fails with boxY located at row 497 - correction done by
1049     // setScrollValues
1050     /*   ypos = 497; // row 497
1051        mouseClick(od, 0, Math.round (ypos * scaleh * av.getCharHeight()));
1052        assertEquals(od.getBoxX(), 0);
1053        assertEquals(
1054                od.getBoxY(),
1055                Math.round ((firstHidden - viewHeight) * scaleh * av.getCharHeight()),
1056                1.5);
1057        assertEquals(od.getBoxWidth(), boxWidth, 1.5);
1058        assertEquals(od.getBoxHeight(), boxHeight, 1.5);*/
1059
1060     // click within hidden rows
1061     ypos = 505;
1062     // TODO: fails with wrong boxHeight - correction done by setScrollValues(?)
1063     /*mouseClick(od, 0, Math.round (ypos * scaleh * av.getCharHeight()));
1064     assertEquals(od.getBoxX(), 0);
1065     assertEquals(
1066             od.getBoxY(),
1067             Math.round ((firstHidden - viewHeight) * scaleh * av.getCharHeight()),
1068             1.5);
1069     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
1070     assertEquals(od.getBoxHeight(), boxHeight, 1.5);*/
1071   }
1072
1073   /*
1074    * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
1075    */
1076   private void moveViewportH(int startRes)
1077   {
1078     int width = av.getEndRes() - av.getStartRes();
1079     av.setStartRes(startRes);
1080     av.setEndRes(startRes + width);
1081     od.setBoxPosition();
1082   }
1083
1084   /*
1085    * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
1086    */
1087   private void moveViewportV(int startSeq)
1088   {
1089     av.setStartSeq(startSeq);
1090     av.setEndSeq(startSeq + viewHeight);
1091     od.setBoxPosition();
1092   }
1093
1094   /*
1095    * Move viewport horizontally and vertically.
1096    */
1097   private void moveViewport(int startRes, int startSeq)
1098   {
1099     int width = av.getEndRes() - av.getStartRes();
1100
1101     av.setStartRes(startRes);
1102     av.setEndRes(startRes + width);
1103     av.setStartSeq(startSeq);
1104     av.setEndSeq(startSeq + viewHeight);
1105     od.setBoxPosition();
1106   }
1107
1108   /*
1109    * Mouse click as position x,y in overview window
1110    */
1111   private void mouseClick(OverviewDimensions od, int x, int y)
1112   {
1113     od.setBoxPositionByMouse(x, y);
1114     // updates require an OverviewPanel to exist which it doesn't here
1115     // so call setBoxPosition() as it would be called by the AlignmentPanel
1116     // normally
1117     int width = av.getEndRes() - av.getStartRes();
1118     int height = av.getEndSeq() - av.getStartSeq();
1119     av.setStartRes(od.getScrollCol());
1120     av.setEndRes(od.getScrollCol() + width);
1121     av.setStartSeq(od.getScrollRow());
1122     av.setEndSeq(od.getScrollRow() + height);
1123     od.setBoxPosition();
1124   }
1125   
1126   private void testBoxIsAtClickPoint(int xpos, int ypos)
1127   {
1128     mouseClick(od, xpos, ypos);
1129     assertEquals(od.getBoxX(), xpos, 1.5);
1130     assertEquals(od.getBoxY(), ypos, 1.5);
1131     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
1132     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
1133
1134   }
1135
1136   /*
1137    * Hide sequences between start and end, using hideseq to do the hiding
1138    * (start <= hideseq <= end. Sequence hideseq is not hidden but the others are
1139    */
1140   private void hideSequences(int start, int end, int hideseq)
1141   {
1142     SequenceGroup sg = new SequenceGroup();
1143     List<SequenceI> allseqs = av.getAlignment().getSequences();
1144     for (int i = start; i <= end; ++i)
1145     {
1146       sg.addSequence(allseqs.get(i), false);
1147     }
1148     av.setSelectionGroup(sg);
1149
1150     /*
1151      * hide group
1152      */
1153     av.hideSequences(allseqs.get(hideseq), true);
1154
1155     while (av.isCalcInProgress())
1156     {
1157       try
1158       {
1159         Thread.sleep(50);
1160       } catch (InterruptedException e)
1161       {
1162         System.out.println("Hiding seqs interruption");
1163       }
1164     }
1165   }
1166
1167   private void hideColumns(int firstHidden, int lastHidden)
1168   {
1169     av.hideColumns(firstHidden, lastHidden);
1170
1171     while (av.isCalcInProgress())
1172     {
1173       try
1174       {
1175         Thread.sleep(50);
1176       } catch (InterruptedException e)
1177       {
1178         System.out.println("Hiding cols interruption");
1179       }
1180     }
1181   }
1182 }