JAL-2388 Renamed viewport position props to viewport ranges
[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   ViewportRanges vpranges;
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     vpranges = new ViewportRanges(al);
79     vpranges.setStartRes(0);
80     vpranges.setEndRes(62);
81     vpranges.setStartSeq(0);
82     vpranges.setEndSeq(17);
83
84     viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1;
85     viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1;
86
87     ColumnSelection hiddenCols = new ColumnSelection();
88
89     od = new OverviewDimensions(vpranges, true);
90     // Initial box sizing - default path through code
91     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
92
93     mouseClick(od, 0, 0);
94     moveViewport(0, 0);
95
96     // calculate before hidden columns so we get absolute values
97     alheight = vpranges.getAbsoluteAlignmentHeight();
98     alwidth = vpranges.getAbsoluteAlignmentWidth();
99
100     boxWidth = Math.round((float) (vpranges.getEndRes()
101             - vpranges.getStartRes() + 1)
102             * od.getWidth() / alwidth);
103     boxHeight = Math.round((float) (vpranges.getEndSeq()
104             - vpranges.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     ViewportRanges props = new ViewportRanges(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 ViewportRanges(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 ViewportRanges(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 ViewportRanges(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 ViewportRanges(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             vpranges);
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             vpranges);
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, vpranges);
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             vpranges);
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, vpranges);
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             vpranges);
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, vpranges);
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     // viewport can't actually extend into hidden cols,
681     // so move to the far right edge of the viewport
682     moveViewport(firstHidden - viewWidth, 0);
683     assertEquals(od.getBoxX(),
684             Math.round((float) (firstHidden - viewWidth)
685                     * od.getWidth() / alwidth));
686     assertEquals(od.getBoxY(), 0);
687     assertEquals(od.getBoxWidth(), boxWidth);
688     assertEquals(od.getBoxHeight(), boxHeight);
689   }
690
691   /**
692    * Test that the box position is set correctly when there are hidden rows at
693    * the start
694    */
695   @Test(groups = { "Functional" })
696   public void testSetBoxFromViewportHiddenRowsAtStart()
697   {
698     int firstHidden = 0;
699     int lastHidden = 20;
700     hideSequences(firstHidden, lastHidden);
701
702     // move viewport to start of alignment:
703     // box moves to below hidden rows, height remains same
704     moveViewport(0, 0);
705     assertEquals(od.getBoxX(), 0);
706     assertEquals(od.getBoxY(),
707             Math.round((float) (lastHidden + 1) * od.getSequencesHeight()
708                     / alheight));
709     assertEquals(od.getBoxWidth(), boxWidth);
710     assertEquals(od.getBoxHeight(), boxHeight);
711
712     // move viewport to end of alignment
713     moveViewport(0, 525 - viewHeight - lastHidden - 1);
714     assertEquals(od.getBoxX(), 0);
715     assertEquals(
716             od.getBoxY(),
717             Math.round((float) (525 - viewHeight) * od.getSequencesHeight()
718                     / alheight));
719     assertEquals(od.getBoxWidth(), boxWidth);
720     assertEquals(od.getBoxHeight(), boxHeight);
721   }
722
723   /**
724    * Test that the box position is set correctly when there are hidden rows in
725    * the middle
726    */
727   @Test(groups = { "Functional" })
728   public void testSetBoxFromViewportHiddenRowsInMiddle()
729   {
730     int firstHidden = 200;
731     int lastHidden = 210;
732     hideSequences(firstHidden, lastHidden);
733
734     // move viewport to start of alignment:
735     // box, height etc as in non-hidden case
736     moveViewport(0, 0);
737     assertEquals(od.getBoxX(), 0);
738     assertEquals(od.getBoxY(), 0);
739     assertEquals(od.getBoxWidth(), boxWidth);
740     assertEquals(od.getBoxHeight(), boxHeight);
741
742     // move viewport to straddle hidden rows
743     moveViewport(0, 198);
744     assertEquals(od.getBoxX(), 0);
745     assertEquals(od.getBoxY(), Math.round ((float)198 * od.getSequencesHeight()
746             / alheight));
747     assertEquals(od.getBoxWidth(), boxWidth);
748     assertEquals(
749             od.getBoxHeight(),
750             Math.round((float) (viewHeight + lastHidden - firstHidden + 1)
751                     * od.getSequencesHeight() / alheight));
752   }
753
754   /**
755    * Test that the box position is set correctly when there are hidden rows at
756    * the bottom
757    */
758   @Test(groups = { "Functional" })
759   public void testSetBoxFromViewportHiddenRowsAtEnd()
760   {
761     int firstHidden = 500;
762     int lastHidden = 524;
763     hideSequences(firstHidden, lastHidden);
764
765     // move viewport to start of alignment:
766     // box, height etc as in non-hidden case
767     moveViewport(0, 0);
768     assertEquals(od.getBoxX(), 0);
769     assertEquals(od.getBoxY(), 0);
770     assertEquals(od.getBoxWidth(), boxWidth);
771     assertEquals(od.getBoxHeight(), boxHeight);
772
773     // move viewport to end of alignment
774     // viewport sits above hidden rows and does not include them
775     moveViewport(0, firstHidden - viewHeight - 1);
776     assertEquals(od.getBoxX(), 0);
777     assertEquals(
778             od.getBoxY(),
779             Math.round((float) (firstHidden - viewHeight - 1)
780                     * od.getSequencesHeight() / alheight));
781     assertEquals(od.getBoxWidth(), boxWidth);
782     assertEquals(od.getBoxHeight(), boxHeight);
783
784   }
785
786   /**
787    * Test setting of the box position, when there are hidden rows at the start
788    * of the alignment
789    */
790   @Test(groups = { "Functional" })
791   public void testFromMouseWithHiddenRowsAtStart()
792   {
793     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
794             vpranges);
795     assertEquals(od.getBoxX(), 0);
796     assertEquals(od.getBoxY(), 0);
797     assertEquals(od.getBoxHeight(), boxHeight);
798     assertEquals(od.getBoxWidth(), boxWidth);
799     assertEquals(od.getScrollCol(), 0);
800     assertEquals(od.getScrollRow(), 0);
801
802     // hide rows at start and check updated box position is correct
803     // changes boxY but not boxheight
804     int lastHiddenRow = 30;
805     hideSequences(0, lastHiddenRow);
806
807     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
808     assertEquals(od.getBoxX(), 0);
809     assertEquals(od.getBoxY(),
810             Math.round((float) (lastHiddenRow + 1)
811                     * od.getSequencesHeight() / alheight));
812     assertEquals(od.getBoxWidth(), boxWidth);
813     assertEquals(od.getBoxHeight(), boxHeight);
814
815     // click in hidden rows - same result
816     mouseClick(od, 0, 0);
817     assertEquals(od.getBoxX(), 0);
818     assertEquals(
819             od.getBoxY(),
820             Math.round((float) (lastHiddenRow + 1)
821                     * od.getSequencesHeight() / alheight));
822     assertEquals(od.getBoxWidth(), boxWidth);
823     assertEquals(od.getBoxHeight(), boxHeight);
824
825     // click below hidden rows
826     mouseClick(od, 0, 150);
827     assertEquals(od.getBoxX(), 0);
828     assertEquals(od.getBoxY(), 150);
829     assertEquals(od.getBoxWidth(), boxWidth);
830     assertEquals(od.getBoxHeight(), boxHeight);
831   }
832
833   /**
834    * Test setting of the box position, when there are hidden rows at the middle
835    * of the alignment
836    */
837   @Test(groups = { "Functional" })
838   public void testFromMouseWithHiddenRowsInMiddle()
839   {
840     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
841             vpranges);
842
843     assertEquals(od.getBoxX(), 0);
844     assertEquals(od.getBoxY(), 0);
845     assertEquals(od.getBoxWidth(), boxWidth);
846     assertEquals(od.getBoxHeight(), boxHeight);
847     assertEquals(od.getScrollCol(), 0);
848     assertEquals(od.getScrollRow(), 0);
849
850     // hide rows in middle and check updated box position is correct
851     // no changes
852     int firstHiddenRow = 50;
853     int lastHiddenRow = 54;
854     hideSequences(firstHiddenRow, lastHiddenRow);
855
856     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
857
858     assertEquals(od.getBoxX(), 0);
859     assertEquals(od.getBoxY(), 0);
860     assertEquals(od.getBoxWidth(), boxWidth);
861     assertEquals(od.getBoxHeight(), boxHeight);
862
863     // click above hidden rows, so that box overlaps
864     int ypos = 35; // column value in residues
865     mouseClick(od, 0,
866             Math.round((float) ypos * od.getSequencesHeight() / alheight));
867     assertEquals(od.getBoxX(), 0);
868     assertEquals(od.getBoxY(),
869             Math.round((float) ypos * od.getSequencesHeight() / alheight));
870     assertEquals(od.getBoxWidth(), boxWidth);
871     assertEquals(
872             od.getBoxHeight(),
873             boxHeight
874                     + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
875                             * od.getSequencesHeight() / alheight));
876
877     // click so that box straddles hidden rows
878     ypos = 44; // column value in residues
879     mouseClick(od, 0,
880             Math.round((float) ypos * od.getSequencesHeight() / alheight));
881     assertEquals(od.getBoxX(), 0);
882     assertEquals(od.getBoxY(),
883             Math.round((float) ypos * od.getSequencesHeight() / alheight));
884     assertEquals(od.getBoxWidth(), boxWidth);
885     assertEquals(
886             od.getBoxHeight(),
887             boxHeight
888                     + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
889                             * od.getSequencesHeight() / alheight));
890   }
891
892   /**
893    * Test setting of the box position, when there are hidden rows at the end of
894    * the alignment
895    */
896   @Test(groups = { "Functional" })
897   public void testFromMouseWithHiddenRowsAtEnd()
898   {
899     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
900             vpranges);
901     assertEquals(od.getBoxX(), 0);
902     assertEquals(od.getBoxY(), 0);
903     assertEquals(od.getBoxWidth(), boxWidth);
904     assertEquals(od.getBoxHeight(), boxHeight);
905     assertEquals(od.getScrollCol(), 0);
906     assertEquals(od.getScrollRow(), 0);
907
908     // hide rows at end and check updated box position is correct
909     // no changes
910     int firstHidden = 500;
911     int lastHidden = 524;
912     hideSequences(firstHidden, lastHidden);
913
914     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
915     assertEquals(od.getBoxX(), 0);
916     assertEquals(od.getBoxY(), 0);
917     assertEquals(od.getBoxWidth(), boxWidth);
918     assertEquals(od.getBoxHeight(), boxHeight);
919
920     // click above hidden rows
921     int ypos = 40; // row 40
922     mouseClick(od, 0,
923             Math.round((float) ypos * od.getSequencesHeight() / alheight));
924     assertEquals(od.getBoxX(), 0);
925     assertEquals(od.getBoxY(),
926             Math.round((float) ypos * od.getSequencesHeight() / alheight));
927     assertEquals(od.getBoxWidth(), boxWidth);
928     assertEquals(od.getBoxHeight(), boxHeight);
929
930     // click above hidden rows so box overlaps
931     // boxY moved upwards, boxHeight remains same
932     ypos = 497; // row 497
933     mouseClick(od, 0,
934             Math.round((float) ypos * od.getSequencesHeight() / alheight));
935     assertEquals(od.getBoxX(), 0);
936     assertEquals(
937             od.getBoxY(),
938             Math.round((float) (firstHidden - viewHeight)
939                     * od.getSequencesHeight() / alheight));
940     assertEquals(od.getBoxWidth(), boxWidth);
941     assertEquals(od.getBoxHeight(), boxHeight);
942
943     // click within hidden rows
944     ypos = 505;
945     mouseClick(od, 0,
946             Math.round((float) ypos * od.getSequencesHeight() / alheight));
947     assertEquals(od.getBoxX(), 0);
948     assertEquals(
949             od.getBoxY(),
950             Math.round((firstHidden - viewHeight) * od.getSequencesHeight()
951                     / alheight));
952     assertEquals(od.getBoxWidth(), boxWidth);
953     assertEquals(od.getBoxHeight(), boxHeight);
954   }
955
956   /*
957    * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
958    */
959   private void moveViewportH(int startRes)
960   {
961     vpranges.setStartRes(startRes);
962     vpranges.setEndRes(startRes + viewWidth - 1);
963     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
964   }
965
966   /*
967    * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
968    */
969   private void moveViewportV(int startSeq)
970   {
971     vpranges.setStartSeq(startSeq);
972     vpranges.setEndSeq(startSeq + viewHeight - 1);
973     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
974   }
975
976   /*
977    * Move viewport horizontally and vertically.
978    */
979   private void moveViewport(int startRes, int startSeq)
980   {
981     vpranges.setStartRes(startRes);
982     vpranges.setEndRes(startRes + viewWidth - 1);
983     vpranges.setStartSeq(startSeq);
984     vpranges.setEndSeq(startSeq + viewHeight - 1);
985     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
986   }
987
988   /*
989    * Mouse click as position x,y in overview window
990    */
991   private void mouseClick(OverviewDimensions od, int x, int y)
992   {
993     od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols,
994             vpranges);
995
996     // updates require an OverviewPanel to exist which it doesn't here
997     // so call setBoxPosition() as it would be called by the AlignmentPanel
998     // normally
999
1000     vpranges.setStartRes(od.getScrollCol());
1001     vpranges.setEndRes(od.getScrollCol() + viewWidth - 1);
1002     vpranges.setStartSeq(od.getScrollRow());
1003     vpranges.setEndSeq(od.getScrollRow() + viewHeight - 1);
1004     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
1005   }
1006   
1007   /*
1008    * Test that the box is positioned with the top left corner at xpos, ypos
1009    * and with the original width and height
1010    */
1011   private void testBoxIsAtClickPoint(int xpos, int ypos)
1012   {
1013     mouseClick(od, xpos, ypos);
1014     assertEquals(od.getBoxX(), xpos);
1015     assertEquals(od.getBoxY(), ypos);
1016     assertEquals(od.getBoxWidth(), boxWidth);
1017     assertEquals(od.getBoxHeight(), boxHeight);
1018
1019   }
1020
1021   /*
1022    * Hide sequences between start and end
1023    */
1024   private void hideSequences(int start, int end)
1025   {
1026     SequenceI[] allseqs = al.getSequencesArray();
1027     SequenceGroup theseSeqs = new SequenceGroup();
1028     
1029     for (int i = start; i <= end; i++)
1030     {
1031       theseSeqs.addSequence(allseqs[i], false);
1032       al.getHiddenSequences().hideSequence(allseqs[i]);
1033     }
1034
1035     hiddenRepSequences.put(allseqs[start], theseSeqs);
1036   }
1037 }