JAL-2388 Moving some alignment panel logic into overview (in progress)
[jalview.git] / test / jalview / viewmodel / OverviewDimensionsTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.viewmodel;
22
23 import static org.testng.Assert.assertEquals;
24
25 import jalview.analysis.AlignmentGenerator;
26 import jalview.datamodel.Alignment;
27 import jalview.datamodel.AlignmentI;
28 import jalview.datamodel.ColumnSelection;
29 import jalview.datamodel.Sequence;
30 import jalview.datamodel.SequenceCollectionI;
31 import jalview.datamodel.SequenceGroup;
32 import jalview.datamodel.SequenceI;
33
34 import java.util.Hashtable;
35
36 import org.testng.annotations.AfterClass;
37 import org.testng.annotations.BeforeClass;
38 import org.testng.annotations.BeforeMethod;
39 import org.testng.annotations.Test;
40
41 @Test(singleThreaded = true)
42 public class OverviewDimensionsTest
43 {
44   AlignmentI al;
45   OverviewDimensions od;
46
47   // cached widths and heights
48   int boxWidth;
49   int boxHeight;
50   int viewHeight;
51   int viewWidth;
52   int alheight;
53   int alwidth;
54
55   ViewportPositionProps posProps;
56
57   Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
58
59   ColumnSelection hiddenCols = new ColumnSelection();
60
61   @BeforeClass(alwaysRun = true)
62   public void setUpJvOptionPane()
63   {
64     // create random alignment
65     AlignmentGenerator gen = new AlignmentGenerator(false);
66     al = gen.generate(157, 525, 123, 5, 5);
67   }
68
69   @BeforeMethod(alwaysRun = true)
70   public void setUp()
71   {
72     if (!hiddenRepSequences.isEmpty())
73     {
74       al.getHiddenSequences().showAll(hiddenRepSequences);
75     }
76     hiddenCols.revealAllHiddenColumns();
77     
78     posProps = new ViewportPositionProps(al);
79     posProps.setStartRes(0);
80     posProps.setEndRes(62);
81     posProps.setStartSeq(0);
82     posProps.setEndSeq(17);
83
84     viewHeight = posProps.getEndSeq() - posProps.getStartSeq() + 1;
85     viewWidth = posProps.getEndRes() - posProps.getStartRes() + 1;
86
87     ColumnSelection hiddenCols = new ColumnSelection();
88
89     od = new OverviewDimensions(posProps, true);
90     // Initial box sizing - default path through code
91     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
92
93     mouseClick(od, 0, 0);
94     moveViewport(0, 0);
95
96     // calculate before hidden columns so we get absolute values
97     alheight = posProps.getAbsoluteAlignmentHeight();
98     alwidth = posProps.getAbsoluteAlignmentWidth();
99
100     boxWidth = Math.round((float) (posProps.getEndRes()
101             - posProps.getStartRes() + 1)
102             * od.getWidth() / alwidth);
103     boxHeight = Math.round((float) (posProps.getEndSeq()
104             - posProps.getStartSeq() + 1)
105             * od.getSequencesHeight() / alheight);
106   }
107
108   @AfterClass(alwaysRun = true)
109   public void cleanUp()
110   {
111     al = null;
112   }
113
114   /**
115    * Test that the OverviewDimensions constructor sets width and height
116    * correctly
117    */
118   @Test(groups = { "Functional" })
119   public void testConstructor()
120   {
121     SequenceI seqa = new Sequence("Seq1", "ABC");
122     SequenceI seqb = new Sequence("Seq2", "ABC");
123     SequenceI seqc = new Sequence("Seq3", "ABC");
124     SequenceI seqd = new Sequence("Seq4", "ABC");
125     SequenceI seqe = new Sequence("Seq5",
126             "ABCABCABCABCABCABCABCABCBACBACBACBAC");
127
128     int defaultGraphHeight = 20;
129     int maxWidth = 400;
130     int minWidth = 120;
131     int maxSeqHeight = 300;
132     int minSeqHeight = 40;
133
134     // test for alignment with width > height
135     SequenceI[] seqs1 = new SequenceI[] { seqa, seqb };
136     Alignment al1 = new Alignment(seqs1);
137     ViewportPositionProps props = new ViewportPositionProps(al1);
138
139     OverviewDimensions od = new OverviewDimensions(props, true);
140     int scaledHeight = 266;
141     assertEquals(od.getGraphHeight(), defaultGraphHeight);
142     assertEquals(od.getSequencesHeight(), scaledHeight);
143     assertEquals(od.getWidth(), maxWidth);
144     assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight);
145
146     // test for alignment with width < height
147     SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd };
148     Alignment al2 = new Alignment(seqs2);
149     props = new ViewportPositionProps(al2);
150
151     od = new OverviewDimensions(props, true);
152     int scaledWidth = 300;
153     assertEquals(od.getGraphHeight(), defaultGraphHeight);
154     assertEquals(od.getSequencesHeight(), maxSeqHeight);
155     assertEquals(od.getWidth(), scaledWidth);
156     assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight);
157
158     // test for alignment with width > height and sequence height scaled below
159     // min value
160     SequenceI[] seqs3 = new SequenceI[] { seqe };
161     Alignment al3 = new Alignment(seqs3);
162     props = new ViewportPositionProps(al3);
163
164     od = new OverviewDimensions(props, true);
165     assertEquals(od.getGraphHeight(), defaultGraphHeight);
166     assertEquals(od.getSequencesHeight(), minSeqHeight);
167     assertEquals(od.getWidth(), maxWidth);
168     assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight);
169
170     // test for alignment with width < height and width scaled below min value
171     SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa,
172         seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd };
173     Alignment al4 = new Alignment(seqs4);
174     props = new ViewportPositionProps(al4);
175
176     od = new OverviewDimensions(props, true);
177     assertEquals(od.getGraphHeight(), defaultGraphHeight);
178     assertEquals(od.getSequencesHeight(), maxSeqHeight);
179     assertEquals(od.getWidth(), minWidth);
180     assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight);
181
182     Alignment al5 = new Alignment(seqs4);
183     props = new ViewportPositionProps(al5);
184
185     od = new OverviewDimensions(props, false);
186     assertEquals(od.getGraphHeight(), 0);
187     assertEquals(od.getSequencesHeight(), maxSeqHeight);
188     assertEquals(od.getWidth(), minWidth);
189     assertEquals(od.getHeight(), maxSeqHeight);
190   }
191
192   /**
193    * Test that validation after mouse adjustments to boxX and boxY sets box
194    * dimensions and scroll values correctly, when there are no hidden rows or
195    * columns.
196    */
197   @Test(groups = { "Functional" })
198   public void testSetBoxFromMouseClick()
199   {
200     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
201             posProps);
202     assertEquals(od.getBoxX(), 0);
203     assertEquals(od.getBoxY(), 0);
204     assertEquals(od.getBoxWidth(), boxWidth);
205     assertEquals(od.getScrollCol(), 0);
206     assertEquals(od.getScrollRow(), 0);
207
208     // negative boxX value reset to 0
209     mouseClick(od, -5, 10);
210     assertEquals(od.getBoxX(), 0);
211     assertEquals(od.getBoxWidth(), boxWidth);
212     assertEquals(od.getBoxHeight(), boxHeight);
213     assertEquals(od.getScrollRow(),
214             Math.round((float) 10 * alheight / od.getSequencesHeight()));
215     assertEquals(od.getScrollCol(), 0);
216
217     // negative boxY value reset to 0
218     mouseClick(od, 6, -2);
219     assertEquals(od.getBoxY(), 0);
220     assertEquals(od.getBoxWidth(), boxWidth);
221     assertEquals(od.getBoxHeight(), boxHeight);
222     assertEquals(od.getScrollCol(),
223             Math.round((float) 6 * alwidth / od.getWidth()));
224     assertEquals(od.getScrollRow(), 0);
225
226     // overly large boxX value reset to width-boxWidth
227     mouseClick(od, 100, 6);
228     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth() + 1);
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     assertEquals(od.getScrollRow(),
247             Math.round((float) od.getBoxY() * alheight
248                     / od.getSequencesHeight()));
249
250     // click past end of alignment, as above
251     mouseClick(od, 3000, 5);
252     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth() + 1);
253     assertEquals(od.getBoxWidth(), boxWidth);
254     assertEquals(od.getBoxHeight(), boxHeight);
255     assertEquals(od.getScrollCol(),
256             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
257     assertEquals(od.getScrollRow(),
258             Math.round((float) od.getBoxY() * alheight
259                     / od.getSequencesHeight()));
260
261     // move viewport so startRes non-zero and then mouseclick
262     moveViewportH(50);
263
264     // click at viewport position
265     int oldboxx = od.getBoxX();
266     int oldboxy = od.getBoxY();
267     mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2);
268     assertEquals(od.getBoxX(), oldboxx + 5);
269     assertEquals(od.getBoxWidth(), boxWidth);
270     assertEquals(od.getBoxHeight(), boxHeight);
271     assertEquals(od.getScrollCol(),
272             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
273     assertEquals(od.getBoxY(), oldboxy + 2);
274     assertEquals(od.getScrollRow(),
275             Math.round((float) od.getBoxY() * alheight
276                     / od.getSequencesHeight()));
277
278     // click at top corner
279     mouseClick(od, 0, 0);
280     assertEquals(od.getBoxX(), 0);
281     assertEquals(od.getScrollCol(), 0);
282     assertEquals(od.getBoxY(), 0);
283     assertEquals(od.getScrollRow(), 0);
284     assertEquals(od.getBoxWidth(), boxWidth);
285     assertEquals(od.getBoxHeight(), boxHeight);
286   }
287
288   /**
289    * Test setting of the box position, when there are hidden cols at the start
290    * of the alignment
291    */
292   @Test(groups = { "Functional" })
293   public void testFromMouseWithHiddenColsAtStart()
294   {
295     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
296             posProps);
297     assertEquals(od.getBoxX(), 0);
298     assertEquals(od.getBoxY(), 0);
299     assertEquals(od.getBoxWidth(), boxWidth);
300     assertEquals(od.getScrollCol(), 0);
301     assertEquals(od.getScrollRow(), 0);
302
303     // hide cols at start and check updated box position is correct
304     // changes boxX but not boxwidth
305     int lastHiddenCol = 30;
306     hiddenCols.hideColumns(0, lastHiddenCol);
307
308     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
309     assertEquals(od.getBoxX(),
310             Math.round((float) (lastHiddenCol + 1) * od.getWidth()
311                     / alwidth));
312     assertEquals(od.getBoxWidth(), boxWidth);
313     assertEquals(od.getBoxHeight(), boxHeight);
314
315     // try to click in hidden cols, check box does not move
316     // this test currently fails as the overview box does not behave like this!
317     int xpos = 10;
318     mouseClick(od, xpos, 0);
319     assertEquals(
320             od.getBoxX(),
321             Math.round((float) (lastHiddenCol + 1) * od.getWidth()
322                     / alwidth));
323     assertEquals(od.getBoxY(), 0);
324     assertEquals(od.getBoxWidth(), boxWidth);
325     assertEquals(od.getBoxHeight(), boxHeight);
326     assertEquals(od.getScrollRow(), 0);
327     assertEquals(od.getScrollCol(), 0);
328
329     // click to right of hidden columns, box moves to click point
330     testBoxIsAtClickPoint(40, 0);
331     assertEquals(od.getScrollRow(), 0);
332     assertEquals(od.getScrollCol(),
333             Math.round((float) 40 * alwidth / od.getWidth())
334                     - (lastHiddenCol + 1));
335
336     // click to right of hidden columns such that box runs over right hand side
337     // of alignment
338     // box position is adjusted away from the edge
339     // overly large boxX value reset to width-boxWidth
340     xpos = 100;
341     mouseClick(od, xpos, 5);
342     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth() + 1);
343     assertEquals(od.getBoxY(), 5);
344     assertEquals(od.getBoxWidth(), boxWidth);
345     assertEquals(od.getBoxHeight(), boxHeight);
346     assertEquals(od.getScrollCol(),
347             Math.round((float) od.getBoxX() * alwidth / od.getWidth())
348                     - (lastHiddenCol + 1));
349     assertEquals(od.getScrollRow(),
350             Math.round((float) od.getBoxY() * alheight
351                     / od.getSequencesHeight()));
352   }
353
354   /**
355    * Test setting of the box position, when there are hidden cols in the middle
356    * of the alignment
357    */
358   @Test(groups = { "Functional" })
359   public void testFromMouseWithHiddenColsInMiddle()
360   {
361     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
362             posProps);
363     assertEquals(od.getBoxX(), 0);
364     assertEquals(od.getBoxY(), 0);
365     assertEquals(od.getBoxWidth(), boxWidth);
366     assertEquals(od.getScrollCol(), 0);
367     assertEquals(od.getScrollRow(), 0);
368     
369     // hide columns 63-73, no change to box position or dimensions
370     int firstHidden = 63;
371     int lastHidden = 73;
372     hiddenCols.hideColumns(firstHidden, lastHidden);
373
374     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
375     assertEquals(od.getBoxX(), 0);
376     assertEquals(od.getBoxY(), 0);
377     assertEquals(od.getBoxWidth(), boxWidth);
378     assertEquals(od.getScrollCol(), 0);
379     assertEquals(od.getScrollRow(), 0);
380
381     // move box so that it overlaps with hidden cols on one side
382     // box width changes, boxX and scrollCol as for unhidden case
383     int xpos = 55 - boxWidth; // 55 is position in overview approx halfway
384                               // between cols 60 and 70
385     mouseClick(od, xpos, 0);
386     assertEquals(od.getBoxX(), xpos);
387     assertEquals(od.getBoxY(), 0);
388     assertEquals(
389             od.getBoxWidth(),
390             Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
391                     * od.getWidth() / alwidth));
392     assertEquals(od.getBoxHeight(), boxHeight);
393     assertEquals(od.getScrollCol(),
394             Math.round(xpos * alwidth / od.getWidth()));
395     assertEquals(od.getScrollRow(), 0);
396
397     // move box so that it completely covers hidden cols
398     // box width changes, boxX and scrollCol as for hidden case
399     xpos = 33;
400     mouseClick(od, xpos, 0);
401     assertEquals(od.getBoxX(), xpos);
402     assertEquals(od.getBoxY(), 0);
403     assertEquals(
404             od.getBoxWidth(),
405             Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
406                     * od.getWidth() / alwidth));
407     assertEquals(od.getBoxHeight(), boxHeight);
408     assertEquals(od.getScrollCol(),
409             Math.round((float) xpos * alwidth / od.getWidth()));
410     assertEquals(od.getScrollRow(), 0);
411
412     // move box so boxX is in hidden cols, box overhangs at right
413     // boxX and scrollCol at left of hidden area, box width extends across
414     // hidden region
415     xpos = 50;
416     mouseClick(od, xpos, 0);
417     assertEquals(od.getBoxX(),
418             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth));
419     assertEquals(od.getBoxY(), 0);
420     assertEquals(
421             od.getBoxWidth(),
422             boxWidth
423                     + Math.round((float) (lastHidden - firstHidden + 1)
424                             * od.getWidth() / alwidth));
425     assertEquals(od.getBoxHeight(), boxHeight);
426     assertEquals(od.getScrollCol(), firstHidden - 1);
427     assertEquals(od.getScrollRow(), 0);
428
429     // move box so boxX is to right of hidden cols, but does not go beyond full
430     // width of alignment
431     // box width, boxX and scrollCol all as for non-hidden case
432     xpos = 75;
433     testBoxIsAtClickPoint(xpos, 0);
434     assertEquals(od.getScrollRow(), 0);
435     assertEquals(od.getScrollCol(),
436             Math.round(xpos * alwidth / od.getWidth())
437                     - (lastHidden - firstHidden + 1));
438     
439     // move box so it goes beyond full width of alignment
440     // boxX, scrollCol adjusted back, box width normal
441     xpos = 3000;
442     mouseClick(od, xpos, 5);
443     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth() + 1);
444     assertEquals(od.getBoxY(), 5);
445     assertEquals(od.getBoxWidth(), boxWidth);
446     assertEquals(od.getBoxHeight(), boxHeight);
447     assertEquals(od.getScrollCol(),
448             Math.round(((float) od.getBoxX() * alwidth / od.getWidth())
449                     - (lastHidden - firstHidden + 1)));
450     assertEquals(od.getScrollRow(),
451             Math.round((float) od.getBoxY() * alheight
452                     / od.getSequencesHeight()));
453
454   }
455
456   /**
457    * Test setting of the box position, when there are hidden cols at the end of
458    * the alignment
459    */
460   @Test(groups = { "Functional" })
461   public void testFromMouseWithHiddenColsAtEnd()
462   {
463     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
464             posProps);
465     assertEquals(od.getBoxX(), 0);
466     assertEquals(od.getBoxY(), 0);
467     assertEquals(od.getBoxWidth(), boxWidth);
468     assertEquals(od.getScrollCol(), 0);
469     assertEquals(od.getScrollRow(), 0);
470
471     // hide columns 140-164, no change to box position or dimensions
472     int firstHidden = 140;
473     int lastHidden = 164;
474     hiddenCols.hideColumns(firstHidden, lastHidden);
475     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
476     assertEquals(od.getBoxX(), 0);
477     assertEquals(od.getBoxY(), 0);
478     assertEquals(od.getBoxWidth(), boxWidth);
479     assertEquals(od.getScrollCol(), 0);
480     assertEquals(od.getScrollRow(), 0);
481
482     // click to left of hidden cols, without overlapping
483     // boxX, scrollCol and width as normal
484     int xpos = 5;
485     testBoxIsAtClickPoint(xpos, 0);
486     assertEquals(od.getScrollRow(), 0);
487     assertEquals(od.getScrollCol(),
488             Math.round((float) xpos * alwidth / od.getWidth()));
489
490     // click to left of hidden cols, with overlap
491     // boxX and scrollCol adjusted for hidden cols, width normal
492     xpos = Math.round((float) 145 * od.getWidth() / alwidth) - boxWidth;
493     mouseClick(od, xpos, 0);
494     assertEquals(od.getBoxX(),
495             Math.round((firstHidden - 1) * od.getWidth() / alwidth)
496                     - boxWidth);
497     assertEquals(od.getBoxY(), 0);
498     assertEquals(od.getBoxWidth(), boxWidth);
499     assertEquals(od.getBoxHeight(), boxHeight);
500     assertEquals(od.getScrollCol(),
501             Math.round(od.getBoxX() * alwidth / od.getWidth()));
502     assertEquals(od.getScrollRow(), 0);
503
504     // click in hidden cols
505     // boxX and scrollCol adjusted for hidden cols, width normal
506     // TODO breaks as above test
507     /*xpos = 115;
508     assertEquals(
509             od.getBoxX(),
510             Math.round((firstHidden - 1) * scalew * av.getCharWidth())
511                     - od.getBoxWidth());
512     assertEquals(od.getBoxY(), 0);
513     assertEquals(od.getBoxWidth(), boxWidth);
514     assertEquals(od.getBoxHeight(), boxHeight);
515     assertEquals(od.getScrollCol(),
516             Math.round(od.getBoxX() * alwidth / od.getWidth()));
517     assertEquals(od.getScrollRow(), 0);*/
518
519     // click off end of alignment
520     // boxX and scrollCol adjusted for hidden cols, width normal
521     // TODO breaks as above test
522     /*    xpos = 3000;
523         assertEquals(
524                 od.getBoxX(),
525                 Math.round((firstHidden - 1) * scalew * av.getCharWidth())
526                         - od.getBoxWidth());
527         assertEquals(od.getBoxY(), 0);
528         assertEquals(od.getBoxWidth(), boxWidth);
529         assertEquals(od.getBoxHeight(), boxHeight);
530         assertEquals(od.getScrollCol(),
531                 Math.round(od.getBoxX() * alwidth / od.getWidth()));
532         assertEquals(od.getScrollRow(), 0);*/
533   }
534
535   /**
536    * Test that the box position is set correctly when set from the viewport,
537    * with no hidden rows or columns
538    */
539   @Test(groups = { "Functional" })
540   public void testSetBoxFromViewport()
541   {
542     // move viewport to start of alignment
543     moveViewport(0, 0);
544     assertEquals(od.getBoxX(), 0);
545     assertEquals(od.getBoxY(), 0);
546     assertEquals(od.getBoxWidth(), boxWidth);
547     assertEquals(od.getBoxHeight(), boxHeight);
548
549     // move viewport to right
550     moveViewportH(70);
551     assertEquals(od.getBoxX(),
552             Math.round((float) 70 * od.getWidth() / alwidth));
553     assertEquals(od.getBoxY(), 0);
554     assertEquals(od.getBoxWidth(), boxWidth);
555     assertEquals(od.getBoxHeight(), boxHeight);
556
557     // move viewport down
558     moveViewportV(100);
559     assertEquals(od.getBoxX(),
560             Math.round((float) 70 * od.getWidth() / alwidth));
561     assertEquals(od.getBoxY(),
562             Math.round(100 * od.getSequencesHeight() / alheight));
563     assertEquals(od.getBoxWidth(), boxWidth);
564     assertEquals(od.getBoxHeight(), boxHeight);
565
566     // move viewport to bottom right
567     moveViewport(98, 508);
568     assertEquals(od.getBoxX(),
569             Math.round((float) 98 * od.getWidth() / alwidth));
570     assertEquals(od.getBoxY(),
571             Math.round((float) 508 * od.getSequencesHeight() / alheight));
572     assertEquals(od.getBoxWidth(), boxWidth);
573     assertEquals(od.getBoxHeight(), boxHeight);
574   }
575
576   /**
577    * Test that the box position is set correctly when there are hidden columns
578    * at the start
579    */
580   @Test(groups = { "Functional" })
581   public void testSetBoxFromViewportHiddenColsAtStart()
582   {
583     int firstHidden = 0;
584     int lastHidden = 20;
585     hiddenCols.hideColumns(firstHidden, lastHidden);
586
587     // move viewport to start of alignment
588     moveViewport(0, 0);
589     assertEquals(od.getBoxX(),
590             Math.round((float) (lastHidden + 1) * od.getWidth() / alwidth));
591     assertEquals(od.getBoxY(), 0);
592     assertEquals(od.getBoxWidth(), boxWidth);
593     assertEquals(od.getBoxHeight(), boxHeight);
594
595     // move viewport to end of alignment - need to make startRes by removing
596     // hidden cols because of how viewport/overview are implemented
597     moveViewport(98 - lastHidden - 1, 0);
598     assertEquals(od.getBoxX(),
599             Math.round((float) 98 * od.getWidth() / alwidth));
600     assertEquals(od.getBoxY(), 0);
601     assertEquals(od.getBoxWidth(), boxWidth);
602     assertEquals(od.getBoxHeight(), boxHeight);
603   }
604
605   /**
606    * Test that the box position is set correctly when there are hidden columns
607    * in the middle
608    */
609   @Test(groups = { "Functional" })
610   public void testSetBoxFromViewportHiddenColsInMiddle()
611   {
612     int firstHidden = 68;
613     int lastHidden = 78;
614     hiddenCols.hideColumns(firstHidden, lastHidden);
615
616     // move viewport before hidden columns
617     moveViewport(3, 0);
618
619     assertEquals(od.getBoxX(),
620             Math.round((float) 3 * od.getWidth() / alwidth));
621     assertEquals(od.getBoxY(), 0);
622     System.out.println(od.getBoxWidth());
623     assertEquals(od.getBoxWidth(), boxWidth);
624     System.out.println(od.getBoxWidth());
625     assertEquals(od.getBoxHeight(), boxHeight);
626
627     // move viewport to left of hidden columns with overlap
628     moveViewport(10, 0);
629     assertEquals(od.getBoxX(),
630             Math.round((float) 10 * od.getWidth() / alwidth));
631     assertEquals(od.getBoxY(), 0);
632     assertEquals(
633             od.getBoxWidth(),
634             boxWidth
635                     + Math.round((float) (lastHidden - firstHidden + 1)
636                             * od.getWidth() / alwidth));
637     assertEquals(od.getBoxHeight(), boxHeight);
638
639     // move viewport to straddle hidden columns
640     moveViewport(63, 0);
641     assertEquals(od.getBoxX(),
642             Math.round((float) 63 * od.getWidth() / alwidth));
643     assertEquals(od.getBoxY(), 0);
644     assertEquals(
645             od.getBoxWidth(),
646             boxWidth
647                     + Math.round((lastHidden - firstHidden + 1)
648                             * od.getWidth() / alwidth));
649     assertEquals(od.getBoxHeight(), boxHeight);
650
651     // move viewport to right of hidden columns, no overlap
652     moveViewport(80 - (lastHidden - firstHidden + 1), 0);
653     assertEquals(od.getBoxX(),
654             Math.round((float) 80 * od.getWidth() / alwidth));
655     assertEquals(od.getBoxY(), 0);
656     assertEquals(od.getBoxWidth(), boxWidth);
657     assertEquals(od.getBoxHeight(), boxHeight);
658
659   }
660
661   /**
662    * Test that the box position is set correctly when there are hidden columns
663    * at the end
664    */
665   @Test(groups = { "Functional" })
666   public void testSetBoxFromViewportHiddenColsAtEnd()
667   {
668     int firstHidden = 152;
669     int lastHidden = 164;
670     hiddenCols.hideColumns(firstHidden, lastHidden);
671
672     // move viewport before hidden columns
673     moveViewport(3, 0);
674     assertEquals(od.getBoxX(),
675             Math.round((float) 3 * od.getWidth() / alwidth));
676     assertEquals(od.getBoxY(), 0);
677     assertEquals(od.getBoxWidth(), boxWidth);
678     assertEquals(od.getBoxHeight(), boxHeight);
679
680     // move viewport to hidden columns
681     moveViewport(102, 0);
682     assertEquals(od.getBoxX(),
683             Math.round((float) 102 * od.getWidth() / alwidth));
684     assertEquals(od.getBoxY(), 0);
685     assertEquals(od.getBoxWidth(), boxWidth
686                     + Math.round((float) (lastHidden - firstHidden)
687                             * od.getWidth() / alwidth));
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             posProps);
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, posProps);
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             posProps);
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 = 60;
854     hideSequences(firstHiddenRow, lastHiddenRow);
855
856     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
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 = 40;
865     // TODO test fails because box does not change height - dealt with by scroll
866     // values
867     /*    mouseClick(od, 0, Math.round (ypos * alheight / od.getSequencesHeight()));
868         assertEquals(od.getBoxX(), 0);
869         assertEquals(od.getBoxY(), Math.round (ypos * alheight / od.getSequencesHeight()),
870                 1.5);
871         assertEquals(od.getBoxWidth(), boxWidth);
872         assertEquals(
873                 od.getBoxHeight(),
874                 boxHeight
875                         + Math.round ((lastHiddenRow - firstHiddenRow + 1) / scaleh / av
876                                 .getCharHeight()));
877     */
878     // click so that box straddles hidden rows
879     ypos = 48;
880     // TODO test fails because box does not change height - dealt with by scroll
881     // values
882     /*mouseClick(od, 0, Math.round (ypos * alheight / od.getSequencesHeight()));
883     assertEquals(od.getBoxX(), 0);
884     assertEquals(od.getBoxY(), Math.round (ypos * alheight / od.getSequencesHeight()),
885             1.5);
886     assertEquals(od.getBoxWidth(), boxWidth);
887     assertEquals(
888             od.getBoxHeight(),
889             boxHeight
890                     + Math.round ((lastHiddenRow - firstHiddenRow + 1) / scaleh / av
891                             .getCharHeight()));*/
892   }
893
894   /**
895    * Test setting of the box position, when there are hidden rows at the end of
896    * the alignment
897    */
898   @Test(groups = { "Functional" })
899   public void testFromMouseWithHiddenRowsAtEnd()
900   {
901     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
902             posProps);
903     assertEquals(od.getBoxX(), 0);
904     assertEquals(od.getBoxY(), 0);
905     assertEquals(od.getBoxWidth(), boxWidth);
906     assertEquals(od.getBoxHeight(), boxHeight);
907     assertEquals(od.getScrollCol(), 0);
908     assertEquals(od.getScrollRow(), 0);
909
910     // hide rows at end and check updated box position is correct
911     // no changes
912     int firstHidden = 500;
913     int lastHidden = 524;
914     hideSequences(firstHidden, lastHidden);
915
916     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
917     assertEquals(od.getBoxX(), 0);
918     assertEquals(od.getBoxY(), 0);
919     assertEquals(od.getBoxWidth(), boxWidth);
920     assertEquals(od.getBoxHeight(), boxHeight);
921
922     // click above hidden rows
923     int ypos = 40; // row 40
924     mouseClick(od, 0,
925             Math.round((float) ypos * od.getSequencesHeight() / alheight));
926     assertEquals(od.getBoxX(), 0);
927     assertEquals(od.getBoxY(),
928             Math.round((float) ypos * od.getSequencesHeight() / alheight));
929     assertEquals(od.getBoxWidth(), boxWidth);
930     assertEquals(od.getBoxHeight(), boxHeight);
931
932     // click above hidden rows so box overlaps
933     // boxY moved upwards, boxHeight remains same
934     // TODO fails with boxY located at row 497 - correction done by
935     // setScrollValues
936     /*   ypos = 497; // row 497
937        mouseClick(od, 0, Math.round (ypos * scaleh * av.getCharHeight()));
938        assertEquals(od.getBoxX(), 0);
939        assertEquals(
940                od.getBoxY(),
941                Math.round ((firstHidden - viewHeight) * scaleh * av.getCharHeight()),
942                1.5);
943        assertEquals(od.getBoxWidth(), boxWidth);
944        assertEquals(od.getBoxHeight(), boxHeight);*/
945
946     // click within hidden rows
947     ypos = 505;
948     // TODO: fails with wrong boxHeight - correction done by setScrollValues(?)
949     /*mouseClick(od, 0, Math.round (ypos * scaleh * av.getCharHeight()));
950     assertEquals(od.getBoxX(), 0);
951     assertEquals(
952             od.getBoxY(),
953             Math.round ((firstHidden - viewHeight) * scaleh * av.getCharHeight()),
954             1.5);
955     assertEquals(od.getBoxWidth(), boxWidth);
956     assertEquals(od.getBoxHeight(), boxHeight);*/
957   }
958
959   /*
960    * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
961    */
962   private void moveViewportH(int startRes)
963   {
964     posProps.setStartRes(startRes);
965     posProps.setEndRes(startRes + viewWidth - 1);
966     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
967   }
968
969   /*
970    * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
971    */
972   private void moveViewportV(int startSeq)
973   {
974     posProps.setStartSeq(startSeq);
975     posProps.setEndSeq(startSeq + viewHeight - 1);
976     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
977   }
978
979   /*
980    * Move viewport horizontally and vertically.
981    */
982   private void moveViewport(int startRes, int startSeq)
983   {
984     posProps.setStartRes(startRes);
985     posProps.setEndRes(startRes + viewWidth - 1);
986     posProps.setStartSeq(startSeq);
987     posProps.setEndSeq(startSeq + viewHeight - 1);
988     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
989   }
990
991   /*
992    * Mouse click as position x,y in overview window
993    */
994   private void mouseClick(OverviewDimensions od, int x, int y)
995   {
996     od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols,
997             posProps);
998
999     // updates require an OverviewPanel to exist which it doesn't here
1000     // so call setBoxPosition() as it would be called by the AlignmentPanel
1001     // normally
1002
1003     posProps.setStartRes(od.getScrollCol());
1004     posProps.setEndRes(od.getScrollCol() + viewWidth - 1);
1005     posProps.setStartSeq(od.getScrollRow());
1006     posProps.setEndSeq(od.getScrollRow() + viewHeight - 1);
1007     od.setBoxPosition(al.getHiddenSequences(), hiddenCols, posProps);
1008   }
1009   
1010   /*
1011    * Test that the box is positioned with the top left corner at xpos, ypos
1012    * and with the original width and height
1013    */
1014   private void testBoxIsAtClickPoint(int xpos, int ypos)
1015   {
1016     mouseClick(od, xpos, ypos);
1017     assertEquals(od.getBoxX(), xpos);
1018     assertEquals(od.getBoxY(), ypos);
1019     assertEquals(od.getBoxWidth(), boxWidth);
1020     assertEquals(od.getBoxHeight(), boxHeight);
1021
1022   }
1023
1024   /*
1025    * Hide sequences between start and end
1026    */
1027   private void hideSequences(int start, int end)
1028   {
1029     SequenceI[] allseqs = al.getSequencesArray();
1030     SequenceGroup theseSeqs = new SequenceGroup();
1031     
1032     for (int i = start; i <= end; i++)
1033     {
1034       theseSeqs.addSequence(allseqs[i], false);
1035       al.getHiddenSequences().hideSequence(allseqs[i]);
1036     }
1037
1038     hiddenRepSequences.put(allseqs[start], theseSeqs);
1039   }
1040 }