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