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