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