JAL-2613 Missed unit test
[jalview.git] / test / jalview / viewmodel / OverviewDimensionsHideHiddenTest.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.datamodel.Alignment;
27 import jalview.datamodel.AlignmentI;
28 import jalview.datamodel.ColumnSelection;
29 import jalview.datamodel.HiddenColumns;
30 import jalview.datamodel.Sequence;
31 import jalview.datamodel.SequenceCollectionI;
32 import jalview.datamodel.SequenceGroup;
33 import jalview.datamodel.SequenceI;
34
35 import java.util.Hashtable;
36
37 import org.testng.annotations.AfterClass;
38 import org.testng.annotations.BeforeClass;
39 import org.testng.annotations.BeforeMethod;
40 import org.testng.annotations.Test;
41
42 @Test(singleThreaded = true)
43 public class OverviewDimensionsHideHiddenTest
44 {
45   AlignmentI al;
46
47   OverviewDimensionsHideHidden od;
48
49   // cached widths and heights
50   int boxWidth;
51   int boxHeight;
52   int viewHeight;
53   int viewWidth;
54   int alheight;
55   int alwidth;
56
57   ViewportRanges vpranges;
58
59   Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<>();
60
61   HiddenColumns hiddenCols = new HiddenColumns();
62
63   @BeforeClass(alwaysRun = true)
64   public void setUpAlignment()
65   {
66     // create random alignment
67     AlignmentGenerator gen = new AlignmentGenerator(false);
68     al = gen.generate(157, 525, 123, 5, 5);
69   }
70
71   @BeforeMethod(alwaysRun = true)
72   public void setUp()
73   {
74     if (!hiddenRepSequences.isEmpty())
75     {
76       al.getHiddenSequences().showAll(hiddenRepSequences);
77     }
78     ColumnSelection colsel = new ColumnSelection();
79     hiddenCols.revealAllHiddenColumns(colsel);
80     
81     vpranges = new ViewportRanges(al);
82     vpranges.setViewportStartAndHeight(0, 18);
83     vpranges.setViewportStartAndWidth(0, 63);
84
85     viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1;
86     viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1;
87
88     HiddenColumns hiddenCols = new HiddenColumns();
89
90     od = new OverviewDimensionsHideHidden(vpranges, true);
91     // Initial box sizing - default path through code
92     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
93
94     mouseClick(od, 0, 0);
95     moveViewport(0, 0);
96
97     // calculate with visible values
98     alheight = vpranges.getVisibleAlignmentHeight();
99     alwidth = vpranges.getVisibleAlignmentWidth();
100
101     boxWidth = Math.round((float) (vpranges.getEndRes()
102             - vpranges.getStartRes() + 1)
103             * od.getWidth() / alwidth);
104     boxHeight = Math.round((float) (vpranges.getEndSeq()
105             - vpranges.getStartSeq() + 1)
106             * od.getSequencesHeight() / alheight);
107   }
108
109   @AfterClass(alwaysRun = true)
110   public void cleanUp()
111   {
112     al = null;
113   }
114
115   /**
116    * Test that the OverviewDimensions constructor sets width and height
117    * correctly
118    */
119   @Test(groups = { "Functional" })
120   public void testConstructor()
121   {
122     SequenceI seqa = new Sequence("Seq1", "ABC");
123     SequenceI seqb = new Sequence("Seq2", "ABC");
124     SequenceI seqc = new Sequence("Seq3", "ABC");
125     SequenceI seqd = new Sequence("Seq4", "ABC");
126     SequenceI seqe = new Sequence("Seq5",
127             "ABCABCABCABCABCABCABCABCBACBACBACBAC");
128
129     int defaultGraphHeight = 20;
130     int maxWidth = 400;
131     int minWidth = 120;
132     int maxSeqHeight = 300;
133     int minSeqHeight = 40;
134
135     // test for alignment with width > height
136     SequenceI[] seqs1 = new SequenceI[] { seqa, seqb };
137     Alignment al1 = new Alignment(seqs1);
138     ViewportRanges props = new ViewportRanges(al1);
139
140     OverviewDimensions od = new OverviewDimensionsHideHidden(props, true);
141     int scaledHeight = 267;
142     assertEquals(od.getGraphHeight(), defaultGraphHeight);
143     assertEquals(od.getSequencesHeight(), scaledHeight);
144     assertEquals(od.getWidth(), maxWidth);
145     assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight);
146
147     // test for alignment with width < height
148     SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd };
149     Alignment al2 = new Alignment(seqs2);
150     props = new ViewportRanges(al2);
151
152     od = new OverviewDimensionsHideHidden(props, true);
153     int scaledWidth = 300;
154     assertEquals(od.getGraphHeight(), defaultGraphHeight);
155     assertEquals(od.getSequencesHeight(), maxSeqHeight);
156     assertEquals(od.getWidth(), scaledWidth);
157     assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight);
158
159     // test for alignment with width > height and sequence height scaled below
160     // min value
161     SequenceI[] seqs3 = new SequenceI[] { seqe };
162     Alignment al3 = new Alignment(seqs3);
163     props = new ViewportRanges(al3);
164
165     od = new OverviewDimensionsHideHidden(props, true);
166     assertEquals(od.getGraphHeight(), defaultGraphHeight);
167     assertEquals(od.getSequencesHeight(), minSeqHeight);
168     assertEquals(od.getWidth(), maxWidth);
169     assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight);
170
171     // test for alignment with width < height and width scaled below min value
172     SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa,
173         seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd };
174     Alignment al4 = new Alignment(seqs4);
175     props = new ViewportRanges(al4);
176
177     od = new OverviewDimensionsHideHidden(props, true);
178     assertEquals(od.getGraphHeight(), defaultGraphHeight);
179     assertEquals(od.getSequencesHeight(), maxSeqHeight);
180     assertEquals(od.getWidth(), minWidth);
181     assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight);
182
183     Alignment al5 = new Alignment(seqs4);
184     props = new ViewportRanges(al5);
185
186     od = new OverviewDimensionsHideHidden(props, false);
187     assertEquals(od.getGraphHeight(), 0);
188     assertEquals(od.getSequencesHeight(), maxSeqHeight);
189     assertEquals(od.getWidth(), minWidth);
190     assertEquals(od.getHeight(), maxSeqHeight);
191   }
192
193   /**
194    * Test that validation after mouse adjustments to boxX and boxY sets box
195    * dimensions and scroll values correctly, when there are no hidden rows or
196    * columns.
197    */
198   @Test(groups = { "Functional" })
199   public void testSetBoxFromMouseClick()
200   {
201     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
202     assertEquals(od.getBoxX(), 0);
203     assertEquals(od.getBoxY(), 0);
204     assertEquals(od.getBoxWidth(), boxWidth);
205     assertEquals(vpranges.getStartRes(), 0);
206     assertEquals(vpranges.getStartSeq(), 0);
207
208     // negative boxX value reset to 0
209     mouseClick(od, -5, 10);
210     assertEquals(od.getBoxX(), 0);
211     assertEquals(od.getBoxWidth(), boxWidth);
212     assertEquals(od.getBoxHeight(), boxHeight);
213     assertEquals(vpranges.getStartSeq() + vpranges.getViewportHeight() / 2,
214             Math.round((float) 10 * alheight / od.getSequencesHeight()));
215     assertEquals(vpranges.getStartRes(), 0);
216
217     // negative boxY value reset to 0
218     mouseClick(od, 6, -2);
219     assertEquals(od.getBoxY(), 0);
220     assertEquals(od.getBoxWidth(), boxWidth);
221     assertEquals(od.getBoxHeight(), boxHeight);
222     assertEquals(vpranges.getStartRes(), 0);
223     assertEquals(vpranges.getStartSeq(), 0);
224
225     // overly large boxX value reset to width-boxWidth
226     mouseClick(od, 101, 6);
227     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
228     assertEquals(od.getBoxY(), 1);
229     assertEquals(od.getBoxWidth(), boxWidth);
230     assertEquals(od.getBoxHeight(), boxHeight);
231     assertEquals(vpranges.getStartRes(),
232             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
233     assertEquals(
234             vpranges.getStartSeq(),
235             Math.round((float) od.getBoxY() * alheight
236                     / od.getSequencesHeight()));
237
238     // overly large boxY value reset to sequenceHeight - boxHeight
239     mouseClick(od, 10, 520);
240     assertEquals(od.getBoxX(), 0);
241     assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight());
242     assertEquals(od.getBoxWidth(), boxWidth);
243     assertEquals(od.getBoxHeight(), boxHeight);
244     assertEquals(vpranges.getStartRes(),
245             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
246
247     // here (float) od.getBoxY() * alheight / od.getSequencesHeight() = 507.5
248     // and round rounds to 508; however we get 507 working with row values
249     // hence the subtraction of 1
250     assertEquals(
251             vpranges.getStartSeq(),
252             Math.round((float) od.getBoxY() * alheight
253                     / od.getSequencesHeight()) - 1);
254
255     // click past end of alignment, as above
256     mouseClick(od, 3000, 5);
257     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
258     assertEquals(od.getBoxWidth(), boxWidth);
259     assertEquals(od.getBoxHeight(), boxHeight);
260     assertEquals(vpranges.getStartRes(),
261             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
262     assertEquals(
263             vpranges.getStartSeq(),
264             Math.round((float) od.getBoxY() * alheight
265                     / od.getSequencesHeight()));
266
267     // move viewport so startRes non-zero and then mouseclick
268     moveViewportH(20);
269
270     // click at viewport position
271     int oldboxx = od.getBoxX();
272     int oldboxy = od.getBoxY();
273     mouseClick(od, od.getBoxX() + od.getBoxWidth() / 2 + 6,
274             od.getBoxY() + od.getBoxHeight() / 2 + 3);
275     assertEquals(od.getBoxX(), oldboxx + 6);
276     assertEquals(od.getBoxWidth(), boxWidth);
277     assertEquals(od.getBoxHeight(), boxHeight);
278     assertEquals(vpranges.getStartRes(),
279             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
280     assertEquals(od.getBoxY(), oldboxy + 3);
281     assertEquals(
282             vpranges.getStartSeq(),
283             Math.round((float) od.getBoxY() * alheight
284                     / od.getSequencesHeight()));
285
286     // click at top corner
287     mouseClick(od, 0, 0);
288     assertEquals(od.getBoxX(), 0);
289     assertEquals(vpranges.getStartRes(), 0);
290     assertEquals(od.getBoxY(), 0);
291     assertEquals(vpranges.getStartSeq(), 0);
292     assertEquals(od.getBoxWidth(), boxWidth);
293     assertEquals(od.getBoxHeight(), boxHeight);
294   }
295
296   /**
297    * Test setting of the box position, when there are hidden cols at the start
298    * of the alignment
299    */
300   @Test(groups = { "Functional" })
301   public void testFromMouseWithHiddenColsAtStart()
302   {
303     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
304     assertEquals(od.getBoxX(), 0);
305     assertEquals(od.getBoxY(), 0);
306     assertEquals(od.getBoxWidth(), boxWidth);
307     assertEquals(vpranges.getStartRes(), 0);
308     assertEquals(vpranges.getStartSeq(), 0);
309
310     // hide cols at start and check updated box position is correct
311     int lastHiddenCol = 30;
312     hiddenCols.hideColumns(0, lastHiddenCol);
313
314     testBoxIsAtClickPoint(boxWidth / 2, boxHeight / 2);
315
316     // click to right of hidden columns, box moves to click point
317     testBoxIsAtClickPoint(41 + boxWidth / 2, boxHeight / 2);
318     assertEquals(vpranges.getStartSeq(), 0);
319     assertEquals(vpranges.getStartRes(),
320             Math.round((float) 41 * alwidth / od.getWidth()));
321
322     // click to right of hidden columns such that box runs over right hand side
323     // of alignment
324     // box position is adjusted away from the edge
325     // overly large boxX value reset to width-boxWidth
326     int xpos = 100 + boxWidth / 2;
327     mouseClick(od, xpos, boxHeight / 2);
328     assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth);
329     assertEquals(od.getBoxY(), 0);
330     assertEquals(od.getBoxWidth(), boxWidth);
331     assertEquals(od.getBoxHeight(), boxHeight);
332     assertEquals(vpranges.getStartRes(),
333             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
334     assertEquals(vpranges.getStartSeq(), 0);
335   }
336
337   /**
338    * Test setting of the box position, when there are hidden cols in the middle
339    * of the alignment
340    */
341   @Test(groups = { "Functional" })
342   public void testFromMouseWithHiddenColsInMiddle()
343   {
344     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
345     testBoxIsAtClickPoint(boxWidth / 2, boxHeight / 2);
346     assertEquals(od.getBoxX(), 0);
347     assertEquals(od.getBoxY(), 0);
348     assertEquals(od.getBoxWidth(), boxWidth);
349     assertEquals(vpranges.getStartRes(), 0);
350     assertEquals(vpranges.getStartSeq(), 0);
351     
352     // hide columns 63-73, no change to box position or dimensions
353     int firstHidden = 63;
354     int lastHidden = 73;
355     hiddenCols.hideColumns(firstHidden, lastHidden);
356
357     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
358     testBoxIsAtClickPoint(boxWidth / 2, boxHeight / 2);
359     assertEquals(od.getBoxX(), 0);
360     assertEquals(od.getBoxY(), 0);
361     assertEquals(od.getBoxWidth(), boxWidth);
362     assertEquals(vpranges.getStartRes(), 0);
363     assertEquals(vpranges.getStartSeq(), 0);
364
365     // move box so that it overlaps with hidden cols on one side
366     // box width, boxX and scrollCol as for unhidden case
367     int xpos = 54 - boxWidth / 2; // 54 is position in overview approx halfway
368                               // between cols 60 and 70
369     mouseClick(od, xpos, boxHeight / 2);
370     testBoxIsAtClickPoint(xpos, boxHeight / 2);
371     assertEquals(vpranges.getStartRes(), 1 + // rounding
372             Math.round((xpos - boxWidth / 2) * alwidth / od.getWidth()));
373     assertEquals(vpranges.getStartSeq(), 0);
374
375     // move box so that it completely covers hidden cols
376     // box width, boxX and scrollCol as for unhidden case
377     xpos = 33;
378     mouseClick(od, xpos, boxHeight / 2);
379     testBoxIsAtClickPoint(xpos, boxHeight / 2);
380     assertEquals(vpranges.getStartRes(),
381             Math.round((float) (xpos - boxWidth / 2) * alwidth
382                     / od.getWidth()));
383     assertEquals(vpranges.getStartSeq(), 0);
384
385     // move box so boxX is in hidden cols, box overhangs at right
386     // boxX and scrollCol at left of hidden area, box width unchanged
387     xpos = Math.round((float) 50 * od.getWidth() / alwidth) + boxWidth / 2;
388     mouseClick(od, xpos, boxHeight / 2);
389     assertEquals(od.getBoxX() + od.getBoxWidth() / 2, xpos);
390     assertEquals(od.getBoxY(), 0);
391     assertEquals(od.getBoxWidth(), boxWidth);
392     assertEquals(od.getBoxHeight(), boxHeight);
393     assertEquals(vpranges.getStartRes(), 50);
394     assertEquals(vpranges.getStartSeq(), 0);
395
396     // move box so boxX is to right of hidden cols, but does not go beyond full
397     // width of alignment
398     // box width, boxX and scrollCol all as for non-hidden case
399     xpos = Math.round((float) 75 * od.getWidth() / alwidth) + boxWidth / 2;
400     mouseClick(od, xpos, boxHeight / 2);
401     assertEquals(od.getBoxX() + od.getBoxWidth() / 2, xpos);
402     assertEquals(od.getBoxY(), 0);
403     assertEquals(od.getBoxWidth(), boxWidth);
404     assertEquals(od.getBoxHeight(), boxHeight);
405     assertEquals(vpranges.getStartSeq(), 0);
406     assertEquals(vpranges.getStartRes(), 75);
407     
408     // move box so it goes beyond full width of alignment
409     // boxX, scrollCol adjusted back, box width normal
410     xpos = 3000;
411     mouseClick(od, xpos, boxHeight / 2);
412     assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth);
413     assertEquals(od.getBoxY(), 0);
414     assertEquals(od.getBoxWidth(), boxWidth);
415     assertEquals(od.getBoxHeight(), boxHeight);
416     assertEquals(vpranges.getStartRes(),
417             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
418     assertEquals(vpranges.getStartSeq(), 0);
419
420   }
421
422   /**
423    * Test setting of the box position, when there are hidden cols at the end of
424    * the alignment
425    */
426   @Test(groups = { "Functional" })
427   public void testFromMouseWithHiddenColsAtEnd()
428   {
429     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
430     assertEquals(od.getBoxX(), 0);
431     assertEquals(od.getBoxY(), 0);
432     assertEquals(od.getBoxWidth(), boxWidth);
433     assertEquals(vpranges.getStartRes(), 0);
434     assertEquals(vpranges.getStartSeq(), 0);
435
436     // hide columns 140-164, no change to box position or dimensions
437     int firstHidden = 140;
438     int lastHidden = 164;
439     hiddenCols.hideColumns(firstHidden, lastHidden);
440     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
441     assertEquals(od.getBoxX(), 0);
442     assertEquals(od.getBoxY(), 0);
443     assertEquals(od.getBoxWidth(), boxWidth);
444     assertEquals(vpranges.getStartRes(), 0);
445     assertEquals(vpranges.getStartSeq(), 0);
446
447     // click to left of hidden cols, without overlapping
448     // boxX, scrollCol and width as normal
449     int xpos = 30;
450     int ypos = 6;
451     testBoxIsAtClickPoint(xpos, ypos);
452     assertEquals(vpranges.getStartSeq(), Math.round(
453             (float) (ypos - boxHeight / 2) * alheight / od.getHeight()));
454     assertEquals(vpranges.getStartRes(), Math.round(
455             (float) (xpos - boxWidth / 2) * alwidth / od.getWidth()));
456
457     // click to left of hidden cols, with overlap
458     // boxX and scrollCol adjusted for hidden cols, width normal
459     xpos = Math.round((float) 144 * od.getWidth() / alwidth) - boxWidth;
460     mouseClick(od, xpos, boxHeight / 2);
461     testBoxIsAtClickPoint(xpos, boxHeight / 2);
462     assertEquals(vpranges.getStartRes(),
463             Math.round((float) (xpos - boxWidth / 2) * alwidth
464                     / od.getWidth()));
465     assertEquals(vpranges.getStartSeq(), 0);
466
467     // click off end of alignment
468     // boxX and scrollCol adjusted backwards, width normal
469     xpos = 3000;
470     mouseClick(od, xpos, 0);
471     assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth);
472     assertEquals(od.getBoxY(), 0);
473     assertEquals(od.getBoxWidth(), boxWidth);
474     assertEquals(od.getBoxHeight(), boxHeight);
475     assertEquals(vpranges.getStartRes(),
476             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
477     assertEquals(vpranges.getStartSeq(), 0);
478   }
479
480   /**
481    * Test that the box position is set correctly when set from the viewport,
482    * with no hidden rows or columns
483    */
484   @Test(groups = { "Functional" })
485   public void testSetBoxFromViewport()
486   {
487     // move viewport to start of alignment
488     moveViewport(0, 0);
489     assertEquals(od.getBoxX(), 0);
490     assertEquals(od.getBoxY(), 0);
491     assertEquals(od.getBoxWidth(), boxWidth);
492     assertEquals(od.getBoxHeight(), boxHeight);
493
494     // move viewport to right
495     moveViewportH(70);
496     assertEquals(od.getBoxX(),
497             Math.round((float) 70 * od.getWidth() / alwidth));
498     assertEquals(od.getBoxY(), 0);
499     assertEquals(od.getBoxWidth(), boxWidth);
500     assertEquals(od.getBoxHeight(), boxHeight);
501
502     // move viewport down
503     moveViewportV(100);
504     assertEquals(od.getBoxX(),
505             Math.round((float) 70 * od.getWidth() / alwidth));
506     assertEquals(od.getBoxY(),
507             Math.round(100 * od.getSequencesHeight() / alheight));
508     assertEquals(od.getBoxWidth(), boxWidth);
509     assertEquals(od.getBoxHeight(), boxHeight);
510
511     // move viewport to bottom right
512     moveViewport(98, 508);
513     assertEquals(od.getBoxX(),
514             Math.round((float) 98 * od.getWidth() / alwidth));
515     assertEquals(od.getBoxY(),
516             Math.round((float) 508 * od.getSequencesHeight() / alheight));
517     assertEquals(od.getBoxWidth(), boxWidth);
518     assertEquals(od.getBoxHeight(), boxHeight);
519   }
520
521   /**
522    * Test that the box position is set correctly when there are hidden columns
523    * at the start
524    */
525   @Test(groups = { "Functional" })
526   public void testSetBoxFromViewportHiddenColsAtStart()
527   {
528     int firstHidden = 0;
529     int lastHidden = 20;
530     hiddenCols.hideColumns(firstHidden, lastHidden);
531
532     // move viewport to start of alignment
533     moveViewport(0, 0);
534     assertEquals(od.getBoxX(), 0);
535     assertEquals(od.getBoxY(), 0);
536     assertEquals(od.getBoxWidth(), boxWidth);
537     assertEquals(od.getBoxHeight(), boxHeight);
538
539     // move viewport to end of alignment - need to make startRes by removing
540     // hidden cols because of how viewport/overview are implemented
541     moveViewport(98 - lastHidden - 1, 0);
542     assertEquals(od.getBoxX(),
543             Math.round((float) (98 - lastHidden - 1) * od.getWidth()
544                     / alwidth));
545     assertEquals(od.getBoxY(), 0);
546     assertEquals(od.getBoxWidth(), boxWidth);
547     assertEquals(od.getBoxHeight(), boxHeight);
548   }
549
550   /**
551    * Test that the box position is set correctly when there are hidden columns
552    * in the middle
553    */
554   @Test(groups = { "Functional" })
555   public void testSetBoxFromViewportHiddenColsInMiddle()
556   {
557     int firstHidden = 68;
558     int lastHidden = 78;
559     hiddenCols.hideColumns(firstHidden, lastHidden);
560
561     // move viewport before hidden columns
562     moveViewport(3, 0);
563
564     assertEquals(od.getBoxX(),
565             Math.round((float) 3 * od.getWidth() / alwidth));
566     assertEquals(od.getBoxY(), 0);
567     assertEquals(od.getBoxWidth(), boxWidth);
568     assertEquals(od.getBoxHeight(), boxHeight);
569
570     // move viewport to left of hidden columns with overlap
571     moveViewport(10, 0);
572     assertEquals(od.getBoxX(),
573             Math.round((float) 10 * od.getWidth() / alwidth));
574     assertEquals(od.getBoxY(), 0);
575     assertEquals(od.getBoxWidth(), boxWidth);
576     assertEquals(od.getBoxHeight(), boxHeight);
577
578     // move viewport to straddle hidden columns
579     moveViewport(63, 0);
580     assertEquals(od.getBoxX(),
581             Math.round((float) 63 * od.getWidth() / alwidth));
582     assertEquals(od.getBoxY(), 0);
583     assertEquals(od.getBoxWidth(), boxWidth);
584     assertEquals(od.getBoxHeight(), boxHeight);
585
586     // move viewport to right of hidden columns, no overlap
587     moveViewport(80 - (lastHidden - firstHidden + 1), 0);
588     assertEquals(od.getBoxX(),
589             Math.round((float) (80 - (lastHidden - firstHidden + 1))
590                     * od.getWidth() / alwidth));
591     assertEquals(od.getBoxY(), 0);
592     assertEquals(od.getBoxWidth(), boxWidth);
593     assertEquals(od.getBoxHeight(), boxHeight);
594
595   }
596
597   /**
598    * Test that the box position is set correctly when there are hidden columns
599    * at the end
600    */
601   @Test(groups = { "Functional" })
602   public void testSetBoxFromViewportHiddenColsAtEnd()
603   {
604     int firstHidden = 152;
605     int lastHidden = 164;
606     hiddenCols.hideColumns(firstHidden, lastHidden);
607
608     // move viewport before hidden columns
609     moveViewport(3, 0);
610     assertEquals(od.getBoxX(),
611             Math.round((float) 3 * od.getWidth() / alwidth));
612     assertEquals(od.getBoxY(), 0);
613     assertEquals(od.getBoxWidth(), boxWidth);
614     assertEquals(od.getBoxHeight(), boxHeight);
615
616     // move viewport to hidden columns
617     // viewport can't actually extend into hidden cols,
618     // so move to the far right edge of the viewport
619     moveViewport(firstHidden - viewWidth, 0);
620     assertEquals(od.getBoxX(),
621             Math.round((float) (firstHidden - viewWidth)
622                     * od.getWidth() / alwidth));
623     assertEquals(od.getBoxY(), 0);
624     assertEquals(od.getBoxWidth(), boxWidth);
625     assertEquals(od.getBoxHeight(), boxHeight);
626   }
627
628   /**
629    * Test that the box position is set correctly when there are hidden rows at
630    * the start
631    */
632   @Test(groups = { "Functional" })
633   public void testSetBoxFromViewportHiddenRowsAtStart()
634   {
635     int firstHidden = 0;
636     int lastHidden = 20;
637     hideSequences(firstHidden, lastHidden);
638
639     // calculate with visible values
640     alheight = vpranges.getVisibleAlignmentHeight();
641     alwidth = vpranges.getVisibleAlignmentWidth();
642
643     boxWidth = Math.round((float) (vpranges.getEndRes()
644             - vpranges.getStartRes() + 1)
645             * od.getWidth() / alwidth);
646     boxHeight = Math.round((float) (vpranges.getEndSeq()
647             - vpranges.getStartSeq() + 1)
648             * od.getSequencesHeight() / alheight);
649
650     // move viewport to start of alignment:
651     // box moves to below hidden rows, height remains same
652     moveViewport(0, 0);
653     assertEquals(od.getBoxX(), 0);
654     assertEquals(od.getBoxY(), 0);
655     assertEquals(od.getBoxWidth(), boxWidth);
656     assertEquals(od.getBoxHeight(), boxHeight);
657
658     // move viewport to end of alignment
659     moveViewport(0, 525 - viewHeight - lastHidden - 1);
660     assertEquals(od.getBoxX(), 0);
661     assertEquals(
662             od.getBoxY(),
663             Math.round((float) (525 - viewHeight - lastHidden - 1)
664                     * od.getSequencesHeight()
665                     / alheight));
666     assertEquals(od.getBoxWidth(), boxWidth);
667     assertEquals(od.getBoxHeight(), boxHeight);
668   }
669
670   /**
671    * Test that the box position is set correctly when there are hidden rows in
672    * the middle
673    */
674   @Test(groups = { "Functional" })
675   public void testSetBoxFromViewportHiddenRowsInMiddle()
676   {
677     int firstHidden = 200;
678     int lastHidden = 210;
679     hideSequences(firstHidden, lastHidden);
680
681     // calculate with visible values
682     alheight = vpranges.getVisibleAlignmentHeight();
683     alwidth = vpranges.getVisibleAlignmentWidth();
684
685     boxWidth = Math.round((float) (vpranges.getEndRes()
686             - vpranges.getStartRes() + 1)
687             * od.getWidth() / alwidth);
688     boxHeight = Math.round((float) (vpranges.getEndSeq()
689             - vpranges.getStartSeq() + 1)
690             * od.getSequencesHeight() / alheight);
691
692     // move viewport to start of alignment:
693     // box, height etc as in non-hidden case
694     moveViewport(0, 0);
695     assertEquals(od.getBoxX(), 0);
696     assertEquals(od.getBoxY(), 0);
697     assertEquals(od.getBoxWidth(), boxWidth);
698     assertEquals(od.getBoxHeight(), boxHeight);
699
700     // move viewport to straddle hidden rows
701     moveViewport(0, 198);
702     assertEquals(od.getBoxX(), 0);
703     assertEquals(od.getBoxY(), Math.round ((float)198 * od.getSequencesHeight()
704             / alheight));
705     assertEquals(od.getBoxWidth(), boxWidth);
706     assertEquals(od.getBoxHeight(), boxHeight);
707   }
708
709   /**
710    * Test that the box position is set correctly when there are hidden rows at
711    * the bottom
712    */
713   @Test(groups = { "Functional" })
714   public void testSetBoxFromViewportHiddenRowsAtEnd()
715   {
716     int firstHidden = 500;
717     int lastHidden = 524;
718     hideSequences(firstHidden, lastHidden);
719
720     // calculate with visible values
721     alheight = vpranges.getVisibleAlignmentHeight();
722     alwidth = vpranges.getVisibleAlignmentWidth();
723
724     boxWidth = Math.round((float) (vpranges.getEndRes()
725             - vpranges.getStartRes() + 1)
726             * od.getWidth() / alwidth);
727     boxHeight = Math.round((float) (vpranges.getEndSeq()
728             - vpranges.getStartSeq() + 1)
729             * od.getSequencesHeight() / alheight);
730
731     // move viewport to start of alignment:
732     // box, height etc as in non-hidden case
733     moveViewport(0, 0);
734     assertEquals(od.getBoxX(), 0);
735     assertEquals(od.getBoxY(), 0);
736     assertEquals(od.getBoxWidth(), boxWidth);
737     assertEquals(od.getBoxHeight(), boxHeight);
738
739     // move viewport to end of alignment
740     // viewport sits above hidden rows and does not include them
741     moveViewport(0, firstHidden - viewHeight - 1);
742     assertEquals(od.getBoxX(), 0);
743     assertEquals(
744             od.getBoxY(),
745             Math.round((float) (firstHidden - viewHeight - 1)
746                     * od.getSequencesHeight() / alheight));
747     assertEquals(od.getBoxWidth(), boxWidth);
748     assertEquals(od.getBoxHeight(), boxHeight);
749
750   }
751
752   /**
753    * Test setting of the box position, when there are hidden rows at the start
754    * of the alignment
755    */
756   @Test(groups = { "Functional" })
757   public void testFromMouseWithHiddenRowsAtStart()
758   {
759     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
760     assertEquals(od.getBoxX(), 0);
761     assertEquals(od.getBoxY(), 0);
762     assertEquals(od.getBoxHeight(), boxHeight);
763     assertEquals(od.getBoxWidth(), boxWidth);
764     assertEquals(vpranges.getStartRes(), 0);
765     assertEquals(vpranges.getStartSeq(), 0);
766
767     // hide rows at start and check updated box position is correct
768     int lastHiddenRow = 30;
769     hideSequences(0, lastHiddenRow);
770
771     // calculate with visible values
772     alheight = vpranges.getVisibleAlignmentHeight();
773     alwidth = vpranges.getVisibleAlignmentWidth();
774
775     boxWidth = Math.round((float) (vpranges.getEndRes()
776             - vpranges.getStartRes() + 1)
777             * od.getWidth() / alwidth);
778     boxHeight = Math.round((float) (vpranges.getEndSeq()
779             - vpranges.getStartSeq() + 1)
780             * od.getSequencesHeight() / alheight);
781
782     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
783     assertEquals(od.getBoxX(), 0);
784     assertEquals(od.getBoxY(), 0);
785     assertEquals(od.getBoxWidth(), boxWidth);
786     assertEquals(od.getBoxHeight(), boxHeight);
787
788     // click below hidden rows
789     mouseClick(od, 0, 151 + boxHeight / 2);
790     assertEquals(od.getBoxX(), 0);
791     assertEquals(od.getBoxY(), 151);
792     assertEquals(od.getBoxWidth(), boxWidth);
793     assertEquals(od.getBoxHeight(), boxHeight);
794   }
795
796   /**
797    * Test setting of the box position, when there are hidden rows at the middle
798    * of the alignment
799    */
800   @Test(groups = { "Functional" })
801   public void testFromMouseWithHiddenRowsInMiddle()
802   {
803     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
804
805     assertEquals(od.getBoxX(), 0);
806     assertEquals(od.getBoxY(), 0);
807     assertEquals(od.getBoxWidth(), boxWidth);
808     assertEquals(od.getBoxHeight(), boxHeight);
809     assertEquals(vpranges.getStartRes(), 0);
810     assertEquals(vpranges.getStartSeq(), 0);
811
812     // hide rows in middle and check updated box position is correct
813     // no changes
814     int firstHiddenRow = 50;
815     int lastHiddenRow = 54;
816     hideSequences(firstHiddenRow, lastHiddenRow);
817
818     // calculate with visible values
819     alheight = vpranges.getVisibleAlignmentHeight();
820     alwidth = vpranges.getVisibleAlignmentWidth();
821
822     boxWidth = Math.round((float) (vpranges.getEndRes()
823             - vpranges.getStartRes() + 1)
824             * od.getWidth() / alwidth);
825     boxHeight = Math.round((float) (vpranges.getEndSeq()
826             - vpranges.getStartSeq() + 1)
827             * od.getSequencesHeight() / alheight);
828
829     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
830
831     assertEquals(od.getBoxX(), 0);
832     assertEquals(od.getBoxY(), 0);
833     assertEquals(od.getBoxWidth(), boxWidth);
834     assertEquals(od.getBoxHeight(), boxHeight);
835
836     // click above hidden rows, so that box overlaps
837     int ypos = 35 + viewHeight / 2; // row value in residues
838     mouseClick(od, 0,
839             Math.round((float) ypos * od.getSequencesHeight() / alheight));
840     assertEquals(od.getBoxX(), 0);
841     assertEquals(od.getBoxY(),
842             Math.round((float) 35 * od.getSequencesHeight() / alheight));
843     assertEquals(od.getBoxWidth(), boxWidth);
844     assertEquals(od.getBoxHeight(), boxHeight);
845
846     // click so that box straddles hidden rows
847     ypos = 45 + viewHeight / 2; // row value in residues
848     mouseClick(od, 0,
849             Math.round((float) ypos * od.getSequencesHeight() / alheight));
850     assertEquals(od.getBoxX(), 0);
851     assertEquals(od.getBoxY(),
852             Math.round((float) 45 * od.getSequencesHeight() / alheight));
853     assertEquals(od.getBoxWidth(), boxWidth);
854     assertEquals(od.getBoxHeight(), boxHeight);
855   }
856
857   /**
858    * Test setting of the box position, when there are hidden rows at the end of
859    * the alignment
860    */
861   @Test(groups = { "Functional" })
862   public void testFromMouseWithHiddenRowsAtEnd()
863   {
864     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
865     assertEquals(od.getBoxX(), 0);
866     assertEquals(od.getBoxY(), 0);
867     assertEquals(od.getBoxWidth(), boxWidth);
868     assertEquals(od.getBoxHeight(), boxHeight);
869     assertEquals(vpranges.getStartRes(), 0);
870     assertEquals(vpranges.getStartSeq(), 0);
871
872     // hide rows at end and check updated box position is correct
873     // no changes
874     int firstHidden = 500;
875     int lastHidden = 524;
876     hideSequences(firstHidden, lastHidden);
877
878     // calculate with visible values
879     alheight = vpranges.getVisibleAlignmentHeight();
880     alwidth = vpranges.getVisibleAlignmentWidth();
881
882     boxWidth = Math.round((float) (vpranges.getEndRes()
883             - vpranges.getStartRes() + 1)
884             * od.getWidth() / alwidth);
885     boxHeight = Math.round((float) (vpranges.getEndSeq()
886             - vpranges.getStartSeq() + 1)
887             * od.getSequencesHeight() / alheight);
888
889     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
890     assertEquals(od.getBoxX(), 0);
891     assertEquals(od.getBoxY(), 0);
892     assertEquals(od.getBoxWidth(), boxWidth);
893     assertEquals(od.getBoxHeight(), boxHeight);
894
895     // click above hidden rows
896     int ypos = 41 + viewHeight / 2; // row 41
897     mouseClick(od, 0,
898             Math.round((float) ypos * od.getSequencesHeight() / alheight));
899     assertEquals(od.getBoxX(), 0);
900     assertEquals(od.getBoxY(),
901             Math.round((float) 41 * od.getSequencesHeight() / alheight));
902     assertEquals(od.getBoxWidth(), boxWidth);
903     assertEquals(od.getBoxHeight(), boxHeight);
904
905     // click above hidden rows so box overlaps
906     // boxY, boxHeight remains same
907     ypos = 497 + viewHeight / 2; // row 497
908     mouseClick(od, 0,
909             Math.round((float) ypos * od.getSequencesHeight() / alheight));
910     assertEquals(od.getBoxX(), 0);
911     assertEquals(
912             od.getBoxY(),
913             Math.round((float) firstHidden * od.getSequencesHeight()
914                     / alheight)
915                     - boxHeight);
916     assertEquals(od.getBoxWidth(), boxWidth);
917     assertEquals(od.getBoxHeight(), boxHeight);
918   }
919
920   /*
921    * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
922    */
923   private void moveViewportH(int startRes)
924   {
925     vpranges.setViewportStartAndWidth(startRes, viewWidth);
926     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
927   }
928
929   /*
930    * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
931    */
932   private void moveViewportV(int startSeq)
933   {
934     vpranges.setViewportStartAndHeight(startSeq, viewHeight);
935     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
936   }
937
938   /*
939    * Move viewport horizontally and vertically.
940    */
941   private void moveViewport(int startRes, int startSeq)
942   {
943     vpranges.setViewportStartAndWidth(startRes, viewWidth);
944     vpranges.setViewportStartAndHeight(startSeq, viewHeight);
945     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
946   }
947
948   /*
949    * Mouse click as position x,y in overview window
950    */
951   private void mouseClick(OverviewDimensions od, int x, int y)
952   {
953     od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols);
954
955     // updates require an OverviewPanel to exist which it doesn't here
956     // so call setBoxPosition() as it would be called by the AlignmentPanel
957     // normally
958     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
959   }
960   
961   /*
962    * Test that the box is positioned with the top left corner at xpos, ypos
963    * and with the original width and height
964    */
965   private void testBoxIsAtClickPoint(int xpos, int ypos)
966   {
967     mouseClick(od, xpos, ypos);
968     assertEquals(od.getBoxX() + od.getBoxWidth() / 2, xpos);
969     assertEquals(od.getBoxY() + od.getBoxHeight() / 2, ypos);
970     assertEquals(od.getBoxWidth(), boxWidth);
971     assertEquals(od.getBoxHeight(), boxHeight);
972
973   }
974
975   /*
976    * Hide sequences between start and end
977    */
978   private void hideSequences(int start, int end)
979   {
980     SequenceI[] allseqs = al.getSequencesArray();
981     SequenceGroup theseSeqs = new SequenceGroup();
982     
983     for (int i = start; i <= end; i++)
984     {
985       theseSeqs.addSequence(allseqs[i], false);
986       al.getHiddenSequences().hideSequence(allseqs[i]);
987     }
988
989     hiddenRepSequences.put(allseqs[start], theseSeqs);
990   }
991 }