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