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