21e3ed3e8acac9ae1f83c5de95da01d633cc7180
[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 import static org.testng.Assert.assertFalse;
25 import static org.testng.Assert.assertTrue;
26
27 import jalview.analysis.AlignmentGenerator;
28 import jalview.datamodel.Alignment;
29 import jalview.datamodel.AlignmentI;
30 import jalview.datamodel.ColumnSelection;
31 import jalview.datamodel.HiddenColumns;
32 import jalview.datamodel.Sequence;
33 import jalview.datamodel.SequenceCollectionI;
34 import jalview.datamodel.SequenceGroup;
35 import jalview.datamodel.SequenceI;
36
37 import java.util.Hashtable;
38
39 import org.testng.annotations.AfterClass;
40 import org.testng.annotations.BeforeClass;
41 import org.testng.annotations.BeforeMethod;
42 import org.testng.annotations.Test;
43
44 @Test(singleThreaded = true)
45 public class OverviewDimensionsShowHiddenTest
46 {
47   AlignmentI al;
48   OverviewDimensionsShowHidden od;
49
50   // cached widths and heights
51   int boxWidth;
52   int boxHeight;
53   int viewHeight;
54   int viewWidth;
55   int alheight;
56   int alwidth;
57
58   ViewportRanges vpranges;
59
60   Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<>();
61
62   HiddenColumns hiddenCols = new HiddenColumns();
63
64   @BeforeClass(alwaysRun = true)
65   public void setUpAlignment()
66   {
67     // create random alignment
68     AlignmentGenerator gen = new AlignmentGenerator(false);
69     al = gen.generate(157, 525, 123, 5, 5);
70   }
71
72   @BeforeMethod(alwaysRun = true)
73   public void setUp()
74   {
75     if (!hiddenRepSequences.isEmpty())
76     {
77       al.getHiddenSequences().showAll(hiddenRepSequences);
78     }
79     ColumnSelection colsel = new ColumnSelection();
80     hiddenCols.revealAllHiddenColumns(colsel);
81     
82     vpranges = new ViewportRanges(al);
83     vpranges.setViewportStartAndHeight(0, 18);
84     vpranges.setViewportStartAndWidth(0, 63);
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(vpranges.getStartRes(), 0);
207     assertEquals(vpranges.getStartSeq(), 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(vpranges.getStartSeq(),
215             Math.round((float) 10 * alheight / od.getSequencesHeight()));
216     assertEquals(vpranges.getStartRes(), 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(vpranges.getStartRes(),
224             Math.round((float) 6 * alwidth / od.getWidth()));
225     assertEquals(vpranges.getStartSeq(), 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(vpranges.getStartRes(),
234             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
235     assertEquals(
236             vpranges.getStartSeq(),
237             Math.round((float) od.getBoxY() * alheight
238                     / od.getSequencesHeight()));
239
240     // overly large boxY value reset to sequenceHeight - boxHeight
241     mouseClick(od, 10, 520);
242     assertEquals(od.getBoxX(), 10);
243     assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight());
244     assertEquals(od.getBoxWidth(), boxWidth);
245     assertEquals(od.getBoxHeight(), boxHeight);
246     assertEquals(vpranges.getStartRes(),
247             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
248
249     // here (float) od.getBoxY() * alheight / od.getSequencesHeight() = 507.5
250     // and round rounds to 508; however we get 507 working with row values
251     // hence the subtraction of 1
252     assertEquals(
253             vpranges.getStartSeq(),
254             Math.round((float) od.getBoxY() * alheight
255                     / od.getSequencesHeight()) - 1);
256
257     // click past end of alignment, as above
258     mouseClick(od, 3000, 5);
259     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
260     assertEquals(od.getBoxWidth(), boxWidth);
261     assertEquals(od.getBoxHeight(), boxHeight);
262     assertEquals(vpranges.getStartRes(),
263             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
264     assertEquals(
265             vpranges.getStartSeq(),
266             Math.round((float) od.getBoxY() * alheight
267                     / od.getSequencesHeight()));
268
269     // move viewport so startRes non-zero and then mouseclick
270     moveViewportH(50);
271
272     // click at viewport position
273     int oldboxx = od.getBoxX();
274     int oldboxy = od.getBoxY();
275     mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2);
276     assertEquals(od.getBoxX(), oldboxx + 5);
277     assertEquals(od.getBoxWidth(), boxWidth);
278     assertEquals(od.getBoxHeight(), boxHeight);
279     assertEquals(vpranges.getStartRes(),
280             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
281     assertEquals(od.getBoxY(), oldboxy + 2);
282     assertEquals(
283             vpranges.getStartSeq(),
284             Math.round((float) od.getBoxY() * alheight
285                     / od.getSequencesHeight()));
286
287     // click at top corner
288     mouseClick(od, 0, 0);
289     assertEquals(od.getBoxX(), 0);
290     assertEquals(vpranges.getStartRes(), 0);
291     assertEquals(od.getBoxY(), 0);
292     assertEquals(vpranges.getStartSeq(), 0);
293     assertEquals(od.getBoxWidth(), boxWidth);
294     assertEquals(od.getBoxHeight(), boxHeight);
295   }
296
297   /**
298    * Test setting of the box position, when there are hidden cols at the start
299    * of the alignment
300    */
301   @Test(groups = { "Functional" })
302   public void testFromMouseWithHiddenColsAtStart()
303   {
304     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
305     assertEquals(od.getBoxX(), 0);
306     assertEquals(od.getBoxY(), 0);
307     assertEquals(od.getBoxWidth(), boxWidth);
308     assertEquals(vpranges.getStartRes(), 0);
309     assertEquals(vpranges.getStartSeq(), 0);
310
311     // hide cols at start and check updated box position is correct
312     // changes boxX but not boxwidth
313     int lastHiddenCol = 30;
314     hiddenCols.hideColumns(0, lastHiddenCol);
315
316     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
317     assertEquals(od.getBoxX(),
318             Math.round((float) (lastHiddenCol + 1) * od.getWidth()
319                     / alwidth));
320     assertEquals(od.getBoxWidth(), boxWidth);
321     assertEquals(od.getBoxHeight(), boxHeight);
322
323     // try to click in hidden cols, check box does not move
324     int xpos = 10;
325     mouseClick(od, xpos, 0);
326     assertEquals(
327             od.getBoxX(),
328             Math.round((float) (lastHiddenCol + 1) * od.getWidth()
329                     / alwidth));
330     assertEquals(od.getBoxY(), 0);
331     assertEquals(od.getBoxWidth(), boxWidth);
332     assertEquals(od.getBoxHeight(), boxHeight);
333     assertEquals(vpranges.getStartSeq(), 0);
334     assertEquals(vpranges.getStartRes(), 0);
335
336     // click to right of hidden columns, box moves to click point
337     testBoxIsAtClickPoint(40, 0);
338     assertEquals(vpranges.getStartSeq(), 0);
339     assertEquals(vpranges.getStartRes(),
340             Math.round((float) 40 * alwidth / od.getWidth())
341                     - (lastHiddenCol + 1));
342
343     // click to right of hidden columns such that box runs over right hand side
344     // of alignment
345     // box position is adjusted away from the edge
346     // overly large boxX value reset to width-boxWidth
347     xpos = 100;
348     mouseClick(od, xpos, 5);
349     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
350     assertEquals(od.getBoxY(), 5);
351     assertEquals(od.getBoxWidth(), boxWidth);
352     assertEquals(od.getBoxHeight(), boxHeight);
353     assertEquals(vpranges.getStartRes(),
354             Math.round((float) od.getBoxX() * alwidth / od.getWidth())
355                     - (lastHiddenCol + 1));
356     assertEquals(
357             vpranges.getStartSeq(),
358             Math.round((float) od.getBoxY() * alheight
359                     / od.getSequencesHeight()));
360   }
361
362   /**
363    * Test setting of the box position, when there are hidden cols in the middle
364    * of the alignment
365    */
366   @Test(groups = { "Functional" })
367   public void testFromMouseWithHiddenColsInMiddle()
368   {
369     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
370     assertEquals(od.getBoxX(), 0);
371     assertEquals(od.getBoxY(), 0);
372     assertEquals(od.getBoxWidth(), boxWidth);
373     assertEquals(vpranges.getStartRes(), 0);
374     assertEquals(vpranges.getStartSeq(), 0);
375     
376     // hide columns 63-73, no change to box position or dimensions
377     int firstHidden = 63;
378     int lastHidden = 73;
379     hiddenCols.hideColumns(firstHidden, lastHidden);
380
381     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
382     assertEquals(od.getBoxX(), 0);
383     assertEquals(od.getBoxY(), 0);
384     assertEquals(od.getBoxWidth(), boxWidth);
385     assertEquals(vpranges.getStartRes(), 0);
386     assertEquals(vpranges.getStartSeq(), 0);
387
388     // move box so that it overlaps with hidden cols on one side
389     // box width changes, boxX and scrollCol as for unhidden case
390     int xpos = 55 - boxWidth; // 55 is position in overview approx halfway
391                               // between cols 60 and 70
392     mouseClick(od, xpos, 0);
393     assertEquals(od.getBoxX(), xpos);
394     assertEquals(od.getBoxY(), 0);
395     assertEquals(
396             od.getBoxWidth(),
397             Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
398                     * od.getWidth() / alwidth));
399     assertEquals(od.getBoxHeight(), boxHeight);
400     assertEquals(vpranges.getStartRes(),
401             Math.round(xpos * alwidth / od.getWidth()));
402     assertEquals(vpranges.getStartSeq(), 0);
403
404     // move box so that it completely covers hidden cols
405     // box width changes, boxX and scrollCol as for hidden case
406     xpos = 33;
407     mouseClick(od, xpos, 0);
408     assertEquals(od.getBoxX(), xpos);
409     assertEquals(od.getBoxY(), 0);
410     assertEquals(
411             od.getBoxWidth(),
412             Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
413                     * od.getWidth() / alwidth));
414     assertEquals(od.getBoxHeight(), boxHeight);
415     assertEquals(vpranges.getStartRes(),
416             Math.round((float) xpos * alwidth / od.getWidth()));
417     assertEquals(vpranges.getStartSeq(), 0);
418
419     // move box so boxX is in hidden cols, box overhangs at right
420     // boxX and scrollCol at left of hidden area, box width extends across
421     // hidden region
422     xpos = 50;
423     mouseClick(od, xpos, 0);
424     assertEquals(od.getBoxX(),
425             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth));
426     assertEquals(od.getBoxY(), 0);
427     assertEquals(
428             od.getBoxWidth(),
429             boxWidth
430                     + Math.round((float) (lastHidden - firstHidden + 1)
431                             * od.getWidth() / alwidth));
432     assertEquals(od.getBoxHeight(), boxHeight);
433     assertEquals(vpranges.getStartRes(), firstHidden - 1);
434     assertEquals(vpranges.getStartSeq(), 0);
435
436     // move box so boxX is to right of hidden cols, but does not go beyond full
437     // width of alignment
438     // box width, boxX and scrollCol all as for non-hidden case
439     xpos = 75;
440     testBoxIsAtClickPoint(xpos, 0);
441     assertEquals(vpranges.getStartSeq(), 0);
442     assertEquals(vpranges.getStartRes(),
443             Math.round(xpos * alwidth / od.getWidth())
444                     - (lastHidden - firstHidden + 1));
445     
446     // move box so it goes beyond full width of alignment
447     // boxX, scrollCol adjusted back, box width normal
448     xpos = 3000;
449     mouseClick(od, xpos, 5);
450     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
451     assertEquals(od.getBoxY(), 5);
452     assertEquals(od.getBoxWidth(), boxWidth);
453     assertEquals(od.getBoxHeight(), boxHeight);
454     assertEquals(
455             vpranges.getStartRes(),
456             Math.round(((float) od.getBoxX() * alwidth / od.getWidth())
457                     - (lastHidden - firstHidden + 1)));
458     assertEquals(
459             vpranges.getStartSeq(),
460             Math.round((float) od.getBoxY() * alheight
461                     / od.getSequencesHeight()));
462
463   }
464
465   /**
466    * Test setting of the box position, when there are hidden cols at the end of
467    * the alignment
468    */
469   @Test(groups = { "Functional" })
470   public void testFromMouseWithHiddenColsAtEnd()
471   {
472     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
473     assertEquals(od.getBoxX(), 0);
474     assertEquals(od.getBoxY(), 0);
475     assertEquals(od.getBoxWidth(), boxWidth);
476     assertEquals(vpranges.getStartRes(), 0);
477     assertEquals(vpranges.getStartSeq(), 0);
478
479     // hide columns 140-164, no change to box position or dimensions
480     int firstHidden = 140;
481     int lastHidden = 164;
482     hiddenCols.hideColumns(firstHidden, lastHidden);
483     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
484     assertEquals(od.getBoxX(), 0);
485     assertEquals(od.getBoxY(), 0);
486     assertEquals(od.getBoxWidth(), boxWidth);
487     assertEquals(vpranges.getStartRes(), 0);
488     assertEquals(vpranges.getStartSeq(), 0);
489
490     // click to left of hidden cols, without overlapping
491     // boxX, scrollCol and width as normal
492     int xpos = 5;
493     testBoxIsAtClickPoint(xpos, 0);
494     assertEquals(vpranges.getStartSeq(), 0);
495     assertEquals(vpranges.getStartRes(),
496             Math.round((float) xpos * alwidth / od.getWidth()));
497
498     // click to left of hidden cols, with overlap
499     // boxX and scrollCol adjusted for hidden cols, width normal
500     xpos = Math.round((float) 145 * od.getWidth() / alwidth) - boxWidth;
501     mouseClick(od, xpos, 0);
502     assertEquals(od.getBoxX(),
503             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
504                     - boxWidth + 1);
505     assertEquals(od.getBoxY(), 0);
506     assertEquals(od.getBoxWidth(), boxWidth);
507     assertEquals(od.getBoxHeight(), boxHeight);
508     assertEquals(vpranges.getStartRes(),
509             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
510     assertEquals(vpranges.getStartSeq(), 0);
511
512     // click in hidden cols
513     // boxX and scrollCol adjusted for hidden cols, width normal
514     xpos = 115;
515     assertEquals(od.getBoxX(),
516             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
517                     - boxWidth + 1);
518     assertEquals(od.getBoxY(), 0);
519     assertEquals(od.getBoxWidth(), boxWidth);
520     assertEquals(od.getBoxHeight(), boxHeight);
521     assertEquals(vpranges.getStartRes(),
522             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
523     assertEquals(vpranges.getStartSeq(), 0);
524
525     // click off end of alignment
526     // boxX and scrollCol adjusted for hidden cols, width normal
527     xpos = 3000;
528     assertEquals(od.getBoxX(),
529             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
530                     - boxWidth + 1);
531     assertEquals(od.getBoxY(), 0);
532     assertEquals(od.getBoxWidth(), boxWidth);
533     assertEquals(od.getBoxHeight(), boxHeight);
534     assertEquals(vpranges.getStartRes(),
535             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
536     assertEquals(vpranges.getStartSeq(), 0);
537   }
538
539   /**
540    * Test that the box position is set correctly when set from the viewport,
541    * with no hidden rows or columns
542    */
543   @Test(groups = { "Functional" })
544   public void testSetBoxFromViewport()
545   {
546     // move viewport to start of alignment
547     moveViewport(0, 0);
548     assertEquals(od.getBoxX(), 0);
549     assertEquals(od.getBoxY(), 0);
550     assertEquals(od.getBoxWidth(), boxWidth);
551     assertEquals(od.getBoxHeight(), boxHeight);
552
553     // move viewport to right
554     moveViewportH(70);
555     assertEquals(od.getBoxX(),
556             Math.round((float) 70 * od.getWidth() / alwidth));
557     assertEquals(od.getBoxY(), 0);
558     assertEquals(od.getBoxWidth(), boxWidth);
559     assertEquals(od.getBoxHeight(), boxHeight);
560
561     // move viewport down
562     moveViewportV(100);
563     assertEquals(od.getBoxX(),
564             Math.round((float) 70 * od.getWidth() / alwidth));
565     assertEquals(od.getBoxY(),
566             Math.round(100 * od.getSequencesHeight() / alheight));
567     assertEquals(od.getBoxWidth(), boxWidth);
568     assertEquals(od.getBoxHeight(), boxHeight);
569
570     // move viewport to bottom right
571     moveViewport(98, 508);
572     assertEquals(od.getBoxX(),
573             Math.round((float) 98 * od.getWidth() / alwidth));
574     assertEquals(od.getBoxY(),
575             Math.round((float) 508 * od.getSequencesHeight() / alheight));
576     assertEquals(od.getBoxWidth(), boxWidth);
577     assertEquals(od.getBoxHeight(), boxHeight);
578   }
579
580   /**
581    * Test that the box position is set correctly when there are hidden columns
582    * at the start
583    */
584   @Test(groups = { "Functional" })
585   public void testSetBoxFromViewportHiddenColsAtStart()
586   {
587     int firstHidden = 0;
588     int lastHidden = 20;
589     hiddenCols.hideColumns(firstHidden, lastHidden);
590
591     // move viewport to start of alignment
592     moveViewport(0, 0);
593     assertEquals(od.getBoxX(),
594             Math.round((float) (lastHidden + 1) * od.getWidth() / alwidth));
595     assertEquals(od.getBoxY(), 0);
596     assertEquals(od.getBoxWidth(), boxWidth);
597     assertEquals(od.getBoxHeight(), boxHeight);
598
599     // move viewport to end of alignment - need to make startRes by removing
600     // hidden cols because of how viewport/overview are implemented
601     moveViewport(98 - lastHidden - 1, 0);
602     assertEquals(od.getBoxX(),
603             Math.round((float) 98 * od.getWidth() / alwidth));
604     assertEquals(od.getBoxY(), 0);
605     assertEquals(od.getBoxWidth(), boxWidth);
606     assertEquals(od.getBoxHeight(), boxHeight);
607   }
608
609   /**
610    * Test that the box position is set correctly when there are hidden columns
611    * in the middle
612    */
613   @Test(groups = { "Functional" })
614   public void testSetBoxFromViewportHiddenColsInMiddle()
615   {
616     int firstHidden = 68;
617     int lastHidden = 78;
618     hiddenCols.hideColumns(firstHidden, lastHidden);
619
620     // move viewport before hidden columns
621     moveViewport(3, 0);
622
623     assertEquals(od.getBoxX(),
624             Math.round((float) 3 * od.getWidth() / alwidth));
625     assertEquals(od.getBoxY(), 0);
626     assertEquals(od.getBoxWidth(), boxWidth);
627     assertEquals(od.getBoxHeight(), boxHeight);
628
629     // move viewport to left of hidden columns with overlap
630     moveViewport(10, 0);
631     assertEquals(od.getBoxX(),
632             Math.round((float) 10 * od.getWidth() / alwidth));
633     assertEquals(od.getBoxY(), 0);
634     assertEquals(
635             od.getBoxWidth(),
636             boxWidth
637                     + Math.round((float) (lastHidden - firstHidden + 1)
638                             * od.getWidth() / alwidth));
639     assertEquals(od.getBoxHeight(), boxHeight);
640
641     // move viewport to straddle hidden columns
642     moveViewport(63, 0);
643     assertEquals(od.getBoxX(),
644             Math.round((float) 63 * od.getWidth() / alwidth));
645     assertEquals(od.getBoxY(), 0);
646     assertEquals(
647             od.getBoxWidth(),
648             boxWidth
649                     + Math.round((lastHidden - firstHidden + 1)
650                             * od.getWidth() / alwidth));
651     assertEquals(od.getBoxHeight(), boxHeight);
652
653     // move viewport to right of hidden columns, no overlap
654     moveViewport(80 - (lastHidden - firstHidden + 1), 0);
655     assertEquals(od.getBoxX(),
656             Math.round((float) 80 * od.getWidth() / alwidth));
657     assertEquals(od.getBoxY(), 0);
658     assertEquals(od.getBoxWidth(), boxWidth);
659     assertEquals(od.getBoxHeight(), boxHeight);
660
661   }
662
663   /**
664    * Test that the box position is set correctly when there are hidden columns
665    * at the end
666    */
667   @Test(groups = { "Functional" })
668   public void testSetBoxFromViewportHiddenColsAtEnd()
669   {
670     int firstHidden = 152;
671     int lastHidden = 164;
672     hiddenCols.hideColumns(firstHidden, lastHidden);
673
674     // move viewport before hidden columns
675     moveViewport(3, 0);
676     assertEquals(od.getBoxX(),
677             Math.round((float) 3 * od.getWidth() / alwidth));
678     assertEquals(od.getBoxY(), 0);
679     assertEquals(od.getBoxWidth(), boxWidth);
680     assertEquals(od.getBoxHeight(), boxHeight);
681
682     // move viewport to hidden columns
683     // viewport can't actually extend into hidden cols,
684     // so move to the far right edge of the viewport
685     moveViewport(firstHidden - viewWidth, 0);
686     assertEquals(od.getBoxX(),
687             Math.round((float) (firstHidden - viewWidth)
688                     * od.getWidth() / alwidth));
689     assertEquals(od.getBoxY(), 0);
690     assertEquals(od.getBoxWidth(), boxWidth);
691     assertEquals(od.getBoxHeight(), boxHeight);
692   }
693
694   /**
695    * Test that the box position is set correctly when there are hidden rows at
696    * the start
697    */
698   @Test(groups = { "Functional" })
699   public void testSetBoxFromViewportHiddenRowsAtStart()
700   {
701     int firstHidden = 0;
702     int lastHidden = 20;
703     hideSequences(firstHidden, lastHidden);
704
705     // move viewport to start of alignment:
706     // box moves to below hidden rows, height remains same
707     moveViewport(0, 0);
708     assertEquals(od.getBoxX(), 0);
709     assertEquals(od.getBoxY(),
710             Math.round((float) (lastHidden + 1) * od.getSequencesHeight()
711                     / alheight));
712     assertEquals(od.getBoxWidth(), boxWidth);
713     assertEquals(od.getBoxHeight(), boxHeight);
714
715     // move viewport to end of alignment
716     moveViewport(0, 525 - viewHeight - lastHidden - 1);
717     assertEquals(od.getBoxX(), 0);
718     assertEquals(
719             od.getBoxY(),
720             Math.round((float) (525 - viewHeight) * od.getSequencesHeight()
721                     / alheight));
722     assertEquals(od.getBoxWidth(), boxWidth);
723     assertEquals(od.getBoxHeight(), boxHeight);
724   }
725
726   /**
727    * Test that the box position is set correctly when there are hidden rows in
728    * the middle
729    */
730   @Test(groups = { "Functional" })
731   public void testSetBoxFromViewportHiddenRowsInMiddle()
732   {
733     int firstHidden = 200;
734     int lastHidden = 210;
735     hideSequences(firstHidden, lastHidden);
736
737     // move viewport to start of alignment:
738     // box, height etc as in non-hidden case
739     moveViewport(0, 0);
740     assertEquals(od.getBoxX(), 0);
741     assertEquals(od.getBoxY(), 0);
742     assertEquals(od.getBoxWidth(), boxWidth);
743     assertEquals(od.getBoxHeight(), boxHeight);
744
745     // move viewport to straddle hidden rows
746     moveViewport(0, 198);
747     assertEquals(od.getBoxX(), 0);
748     assertEquals(od.getBoxY(), Math.round ((float)198 * od.getSequencesHeight()
749             / alheight));
750     assertEquals(od.getBoxWidth(), boxWidth);
751     assertEquals(
752             od.getBoxHeight(),
753             Math.round((float) (viewHeight + lastHidden - firstHidden + 1)
754                     * od.getSequencesHeight() / alheight));
755   }
756
757   /**
758    * Test that the box position is set correctly when there are hidden rows at
759    * the bottom
760    */
761   @Test(groups = { "Functional" })
762   public void testSetBoxFromViewportHiddenRowsAtEnd()
763   {
764     int firstHidden = 500;
765     int lastHidden = 524;
766     hideSequences(firstHidden, lastHidden);
767
768     // move viewport to start of alignment:
769     // box, height etc as in non-hidden case
770     moveViewport(0, 0);
771     assertEquals(od.getBoxX(), 0);
772     assertEquals(od.getBoxY(), 0);
773     assertEquals(od.getBoxWidth(), boxWidth);
774     assertEquals(od.getBoxHeight(), boxHeight);
775
776     // move viewport to end of alignment
777     // viewport sits above hidden rows and does not include them
778     moveViewport(0, firstHidden - viewHeight - 1);
779     assertEquals(od.getBoxX(), 0);
780     assertEquals(
781             od.getBoxY(),
782             Math.round((float) (firstHidden - viewHeight - 1)
783                     * od.getSequencesHeight() / alheight));
784     assertEquals(od.getBoxWidth(), boxWidth);
785     assertEquals(od.getBoxHeight(), boxHeight);
786
787   }
788
789   /**
790    * Test setting of the box position, when there are hidden rows at the start
791    * of the alignment
792    */
793   @Test(groups = { "Functional" })
794   public void testFromMouseWithHiddenRowsAtStart()
795   {
796     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
797     assertEquals(od.getBoxX(), 0);
798     assertEquals(od.getBoxY(), 0);
799     assertEquals(od.getBoxHeight(), boxHeight);
800     assertEquals(od.getBoxWidth(), boxWidth);
801     assertEquals(vpranges.getStartRes(), 0);
802     assertEquals(vpranges.getStartSeq(), 0);
803
804     // hide rows at start and check updated box position is correct
805     // changes boxY but not boxheight
806     int lastHiddenRow = 30;
807     hideSequences(0, lastHiddenRow);
808
809     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
810     assertEquals(od.getBoxX(), 0);
811     assertEquals(od.getBoxY(),
812             Math.round((float) (lastHiddenRow + 1)
813                     * od.getSequencesHeight() / alheight));
814     assertEquals(od.getBoxWidth(), boxWidth);
815     assertEquals(od.getBoxHeight(), boxHeight);
816
817     // click in hidden rows - same result
818     mouseClick(od, 0, 0);
819     assertEquals(od.getBoxX(), 0);
820     assertEquals(
821             od.getBoxY(),
822             Math.round((float) (lastHiddenRow + 1)
823                     * od.getSequencesHeight() / alheight));
824     assertEquals(od.getBoxWidth(), boxWidth);
825     assertEquals(od.getBoxHeight(), boxHeight);
826
827     // click below hidden rows
828     mouseClick(od, 0, 150);
829     assertEquals(od.getBoxX(), 0);
830     assertEquals(od.getBoxY(), 150);
831     assertEquals(od.getBoxWidth(), boxWidth);
832     assertEquals(od.getBoxHeight(), boxHeight);
833   }
834
835   /**
836    * Test setting of the box position, when there are hidden rows at the middle
837    * of the alignment
838    */
839   @Test(groups = { "Functional" })
840   public void testFromMouseWithHiddenRowsInMiddle()
841   {
842     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
843
844     assertEquals(od.getBoxX(), 0);
845     assertEquals(od.getBoxY(), 0);
846     assertEquals(od.getBoxWidth(), boxWidth);
847     assertEquals(od.getBoxHeight(), boxHeight);
848     assertEquals(vpranges.getStartRes(), 0);
849     assertEquals(vpranges.getStartSeq(), 0);
850
851     // hide rows in middle and check updated box position is correct
852     // no changes
853     int firstHiddenRow = 50;
854     int lastHiddenRow = 54;
855     hideSequences(firstHiddenRow, lastHiddenRow);
856
857     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
858
859     assertEquals(od.getBoxX(), 0);
860     assertEquals(od.getBoxY(), 0);
861     assertEquals(od.getBoxWidth(), boxWidth);
862     assertEquals(od.getBoxHeight(), boxHeight);
863
864     // click above hidden rows, so that box overlaps
865     int ypos = 35; // column value in residues
866     mouseClick(od, 0,
867             Math.round((float) ypos * od.getSequencesHeight() / alheight));
868     assertEquals(od.getBoxX(), 0);
869     assertEquals(od.getBoxY(),
870             Math.round((float) ypos * od.getSequencesHeight() / alheight));
871     assertEquals(od.getBoxWidth(), boxWidth);
872     assertEquals(
873             od.getBoxHeight(),
874             boxHeight
875                     + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
876                             * od.getSequencesHeight() / alheight));
877
878     // click so that box straddles hidden rows
879     ypos = 44; // column value in residues
880     mouseClick(od, 0,
881             Math.round((float) ypos * od.getSequencesHeight() / alheight));
882     assertEquals(od.getBoxX(), 0);
883     assertEquals(od.getBoxY(),
884             Math.round((float) ypos * od.getSequencesHeight() / alheight));
885     assertEquals(od.getBoxWidth(), boxWidth);
886     assertEquals(
887             od.getBoxHeight(),
888             boxHeight
889                     + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
890                             * od.getSequencesHeight() / alheight));
891   }
892
893   /**
894    * Test setting of the box position, when there are hidden rows at the end of
895    * the alignment
896    */
897   @Test(groups = { "Functional" })
898   public void testFromMouseWithHiddenRowsAtEnd()
899   {
900     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
901     assertEquals(od.getBoxX(), 0);
902     assertEquals(od.getBoxY(), 0);
903     assertEquals(od.getBoxWidth(), boxWidth);
904     assertEquals(od.getBoxHeight(), boxHeight);
905     assertEquals(vpranges.getStartRes(), 0);
906     assertEquals(vpranges.getStartSeq(), 0);
907
908     // hide rows at end and check updated box position is correct
909     // no changes
910     int firstHidden = 500;
911     int lastHidden = 524;
912     hideSequences(firstHidden, lastHidden);
913
914     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
915     assertEquals(od.getBoxX(), 0);
916     assertEquals(od.getBoxY(), 0);
917     assertEquals(od.getBoxWidth(), boxWidth);
918     assertEquals(od.getBoxHeight(), boxHeight);
919
920     // click above hidden rows
921     int ypos = 40; // row 40
922     mouseClick(od, 0,
923             Math.round((float) ypos * od.getSequencesHeight() / alheight));
924     assertEquals(od.getBoxX(), 0);
925     assertEquals(od.getBoxY(),
926             Math.round((float) ypos * od.getSequencesHeight() / alheight));
927     assertEquals(od.getBoxWidth(), boxWidth);
928     assertEquals(od.getBoxHeight(), boxHeight);
929
930     // click above hidden rows so box overlaps
931     // boxY moved upwards, boxHeight remains same
932     ypos = 497; // row 497
933     mouseClick(od, 0,
934             Math.round((float) ypos * od.getSequencesHeight() / alheight));
935     assertEquals(od.getBoxX(), 0);
936     assertEquals(
937             od.getBoxY(),
938             Math.round((float) (firstHidden - viewHeight)
939                     * od.getSequencesHeight() / alheight));
940     assertEquals(od.getBoxWidth(), boxWidth);
941     assertEquals(od.getBoxHeight(), boxHeight);
942
943     // click within hidden rows
944     ypos = 505;
945     mouseClick(od, 0,
946             Math.round((float) ypos * od.getSequencesHeight() / alheight));
947     assertEquals(od.getBoxX(), 0);
948     assertEquals(
949             od.getBoxY(),
950             Math.round((firstHidden - viewHeight) * od.getSequencesHeight()
951                     / alheight));
952     assertEquals(od.getBoxWidth(), boxWidth);
953     assertEquals(od.getBoxHeight(), boxHeight);
954   }
955
956   /**
957    * Test the function to determine if a point is in the overview's box or not
958    */
959   @Test(groups = { "Functional" })
960   public void testPositionInBox()
961   {
962     assertFalse(od.isPositionInBox(0, 0));
963     assertTrue(od.isPositionInBox(10, 9));
964     assertFalse(od.isPositionInBox(0, 9));
965     assertFalse(od.isPositionInBox(9, 0));
966     assertFalse(od.isPositionInBox(75, 20));
967   }
968
969   /*
970    * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
971    */
972   private void moveViewportH(int startRes)
973   {
974     vpranges.setViewportStartAndWidth(startRes, viewWidth);
975     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
976   }
977
978   /*
979    * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
980    */
981   private void moveViewportV(int startSeq)
982   {
983     vpranges.setViewportStartAndHeight(startSeq, viewHeight);
984     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
985   }
986
987   /*
988    * Move viewport horizontally and vertically.
989    */
990   private void moveViewport(int startRes, int startSeq)
991   {
992     vpranges.setViewportStartAndWidth(startRes, viewWidth);
993     vpranges.setViewportStartAndHeight(startSeq, viewHeight);
994     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
995   }
996
997   /*
998    * Mouse click as position x,y in overview window
999    */
1000   private void mouseClick(OverviewDimensions od, int x, int y)
1001   {
1002     od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols);
1003
1004     // updates require an OverviewPanel to exist which it doesn't here
1005     // so call setBoxPosition() as it would be called by the AlignmentPanel
1006     // normally
1007     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
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 }