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