Merge branch 'bug/JAL-2630gradColourUpdateOverview' into develop
[jalview.git] / test / jalview / viewmodel / OverviewDimensionsShowHiddenTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.viewmodel;
22
23 import static org.testng.Assert.assertEquals;
24
25 import jalview.analysis.AlignmentGenerator;
26 import jalview.datamodel.Alignment;
27 import jalview.datamodel.AlignmentI;
28 import jalview.datamodel.ColumnSelection;
29 import jalview.datamodel.HiddenColumns;
30 import jalview.datamodel.Sequence;
31 import jalview.datamodel.SequenceCollectionI;
32 import jalview.datamodel.SequenceGroup;
33 import jalview.datamodel.SequenceI;
34
35 import java.util.Hashtable;
36
37 import org.testng.annotations.AfterClass;
38 import org.testng.annotations.BeforeClass;
39 import org.testng.annotations.BeforeMethod;
40 import org.testng.annotations.Test;
41
42 @Test(singleThreaded = true)
43 public class OverviewDimensionsShowHiddenTest
44 {
45   AlignmentI al;
46   OverviewDimensionsShowHidden od;
47
48   // cached widths and heights
49   int boxWidth;
50   int boxHeight;
51   int viewHeight;
52   int viewWidth;
53   int alheight;
54   int alwidth;
55
56   ViewportRanges vpranges;
57
58   Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
59
60   HiddenColumns hiddenCols = new HiddenColumns();
61
62   @BeforeClass(alwaysRun = true)
63   public void setUpAlignment()
64   {
65     // create random alignment
66     AlignmentGenerator gen = new AlignmentGenerator(false);
67     al = gen.generate(157, 525, 123, 5, 5);
68   }
69
70   @BeforeMethod(alwaysRun = true)
71   public void setUp()
72   {
73     if (!hiddenRepSequences.isEmpty())
74     {
75       al.getHiddenSequences().showAll(hiddenRepSequences);
76     }
77     ColumnSelection colsel = new ColumnSelection();
78     hiddenCols.revealAllHiddenColumns(colsel);
79     
80     vpranges = new ViewportRanges(al);
81     vpranges.setViewportStartAndHeight(0, 18);
82     vpranges.setViewportStartAndWidth(0, 63);
83
84     viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1;
85     viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1;
86
87     HiddenColumns hiddenCols = new HiddenColumns();
88
89     od = new OverviewDimensionsShowHidden(vpranges, true);
90     // Initial box sizing - default path through code
91     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
92
93     mouseClick(od, 0, 0);
94     moveViewport(0, 0);
95
96     // calculate before hidden columns so we get absolute values
97     alheight = vpranges.getAbsoluteAlignmentHeight();
98     alwidth = vpranges.getAbsoluteAlignmentWidth();
99
100     boxWidth = Math.round((float) (vpranges.getEndRes()
101             - vpranges.getStartRes() + 1)
102             * od.getWidth() / alwidth);
103     boxHeight = Math.round((float) (vpranges.getEndSeq()
104             - vpranges.getStartSeq() + 1)
105             * od.getSequencesHeight() / alheight);
106   }
107
108   @AfterClass(alwaysRun = true)
109   public void cleanUp()
110   {
111     al = null;
112   }
113
114   /**
115    * Test that the OverviewDimensions constructor sets width and height
116    * correctly
117    */
118   @Test(groups = { "Functional" })
119   public void testConstructor()
120   {
121     SequenceI seqa = new Sequence("Seq1", "ABC");
122     SequenceI seqb = new Sequence("Seq2", "ABC");
123     SequenceI seqc = new Sequence("Seq3", "ABC");
124     SequenceI seqd = new Sequence("Seq4", "ABC");
125     SequenceI seqe = new Sequence("Seq5",
126             "ABCABCABCABCABCABCABCABCBACBACBACBAC");
127
128     int defaultGraphHeight = 20;
129     int maxWidth = 400;
130     int minWidth = 120;
131     int maxSeqHeight = 300;
132     int minSeqHeight = 40;
133
134     // test for alignment with width > height
135     SequenceI[] seqs1 = new SequenceI[] { seqa, seqb };
136     Alignment al1 = new Alignment(seqs1);
137     ViewportRanges props = new ViewportRanges(al1);
138
139     OverviewDimensions od = new OverviewDimensionsShowHidden(props, true);
140     int scaledHeight = 267;
141     assertEquals(od.getGraphHeight(), defaultGraphHeight);
142     assertEquals(od.getSequencesHeight(), scaledHeight);
143     assertEquals(od.getWidth(), maxWidth);
144     assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight);
145
146     // test for alignment with width < height
147     SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd };
148     Alignment al2 = new Alignment(seqs2);
149     props = new ViewportRanges(al2);
150
151     od = new OverviewDimensionsShowHidden(props, true);
152     int scaledWidth = 300;
153     assertEquals(od.getGraphHeight(), defaultGraphHeight);
154     assertEquals(od.getSequencesHeight(), maxSeqHeight);
155     assertEquals(od.getWidth(), scaledWidth);
156     assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight);
157
158     // test for alignment with width > height and sequence height scaled below
159     // min value
160     SequenceI[] seqs3 = new SequenceI[] { seqe };
161     Alignment al3 = new Alignment(seqs3);
162     props = new ViewportRanges(al3);
163
164     od = new OverviewDimensionsShowHidden(props, true);
165     assertEquals(od.getGraphHeight(), defaultGraphHeight);
166     assertEquals(od.getSequencesHeight(), minSeqHeight);
167     assertEquals(od.getWidth(), maxWidth);
168     assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight);
169
170     // test for alignment with width < height and width scaled below min value
171     SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa,
172         seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd };
173     Alignment al4 = new Alignment(seqs4);
174     props = new ViewportRanges(al4);
175
176     od = new OverviewDimensionsShowHidden(props, true);
177     assertEquals(od.getGraphHeight(), defaultGraphHeight);
178     assertEquals(od.getSequencesHeight(), maxSeqHeight);
179     assertEquals(od.getWidth(), minWidth);
180     assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight);
181
182     Alignment al5 = new Alignment(seqs4);
183     props = new ViewportRanges(al5);
184
185     od = new OverviewDimensionsShowHidden(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     assertEquals(od.getBoxX(), 0);
202     assertEquals(od.getBoxY(), 0);
203     assertEquals(od.getBoxWidth(), boxWidth);
204     assertEquals(vpranges.getStartRes(), 0);
205     assertEquals(vpranges.getStartSeq(), 0);
206
207     // negative boxX value reset to 0
208     mouseClick(od, -5, 10);
209     assertEquals(od.getBoxX(), 0);
210     assertEquals(od.getBoxWidth(), boxWidth);
211     assertEquals(od.getBoxHeight(), boxHeight);
212     assertEquals(vpranges.getStartSeq(),
213             Math.round((float) 10 * alheight / od.getSequencesHeight()));
214     assertEquals(vpranges.getStartRes(), 0);
215
216     // negative boxY value reset to 0
217     mouseClick(od, 6, -2);
218     assertEquals(od.getBoxY(), 0);
219     assertEquals(od.getBoxWidth(), boxWidth);
220     assertEquals(od.getBoxHeight(), boxHeight);
221     assertEquals(vpranges.getStartRes(),
222             Math.round((float) 6 * alwidth / od.getWidth()));
223     assertEquals(vpranges.getStartSeq(), 0);
224
225     // overly large boxX value reset to width-boxWidth
226     mouseClick(od, 100, 6);
227     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
228     assertEquals(od.getBoxY(), 6);
229     assertEquals(od.getBoxWidth(), boxWidth);
230     assertEquals(od.getBoxHeight(), boxHeight);
231     assertEquals(vpranges.getStartRes(),
232             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
233     assertEquals(
234             vpranges.getStartSeq(),
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(vpranges.getStartRes(),
245             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
246
247     // here (float) od.getBoxY() * alheight / od.getSequencesHeight() = 507.5
248     // and round rounds to 508; however we get 507 working with row values
249     // hence the subtraction of 1
250     assertEquals(
251             vpranges.getStartSeq(),
252             Math.round((float) od.getBoxY() * alheight
253                     / od.getSequencesHeight()) - 1);
254
255     // click past end of alignment, as above
256     mouseClick(od, 3000, 5);
257     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
258     assertEquals(od.getBoxWidth(), boxWidth);
259     assertEquals(od.getBoxHeight(), boxHeight);
260     assertEquals(vpranges.getStartRes(),
261             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
262     assertEquals(
263             vpranges.getStartSeq(),
264             Math.round((float) od.getBoxY() * alheight
265                     / od.getSequencesHeight()));
266
267     // move viewport so startRes non-zero and then mouseclick
268     moveViewportH(50);
269
270     // click at viewport position
271     int oldboxx = od.getBoxX();
272     int oldboxy = od.getBoxY();
273     mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2);
274     assertEquals(od.getBoxX(), oldboxx + 5);
275     assertEquals(od.getBoxWidth(), boxWidth);
276     assertEquals(od.getBoxHeight(), boxHeight);
277     assertEquals(vpranges.getStartRes(),
278             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
279     assertEquals(od.getBoxY(), oldboxy + 2);
280     assertEquals(
281             vpranges.getStartSeq(),
282             Math.round((float) od.getBoxY() * alheight
283                     / od.getSequencesHeight()));
284
285     // click at top corner
286     mouseClick(od, 0, 0);
287     assertEquals(od.getBoxX(), 0);
288     assertEquals(vpranges.getStartRes(), 0);
289     assertEquals(od.getBoxY(), 0);
290     assertEquals(vpranges.getStartSeq(), 0);
291     assertEquals(od.getBoxWidth(), boxWidth);
292     assertEquals(od.getBoxHeight(), boxHeight);
293   }
294
295   /**
296    * Test setting of the box position, when there are hidden cols at the start
297    * of the alignment
298    */
299   @Test(groups = { "Functional" })
300   public void testFromMouseWithHiddenColsAtStart()
301   {
302     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
303     assertEquals(od.getBoxX(), 0);
304     assertEquals(od.getBoxY(), 0);
305     assertEquals(od.getBoxWidth(), boxWidth);
306     assertEquals(vpranges.getStartRes(), 0);
307     assertEquals(vpranges.getStartSeq(), 0);
308
309     // hide cols at start and check updated box position is correct
310     // changes boxX but not boxwidth
311     int lastHiddenCol = 30;
312     hiddenCols.hideColumns(0, lastHiddenCol);
313
314     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
315     assertEquals(od.getBoxX(),
316             Math.round((float) (lastHiddenCol + 1) * od.getWidth()
317                     / alwidth));
318     assertEquals(od.getBoxWidth(), boxWidth);
319     assertEquals(od.getBoxHeight(), boxHeight);
320
321     // try to click in hidden cols, check box does not move
322     int xpos = 10;
323     mouseClick(od, xpos, 0);
324     assertEquals(
325             od.getBoxX(),
326             Math.round((float) (lastHiddenCol + 1) * od.getWidth()
327                     / alwidth));
328     assertEquals(od.getBoxY(), 0);
329     assertEquals(od.getBoxWidth(), boxWidth);
330     assertEquals(od.getBoxHeight(), boxHeight);
331     assertEquals(vpranges.getStartSeq(), 0);
332     assertEquals(vpranges.getStartRes(), 0);
333
334     // click to right of hidden columns, box moves to click point
335     testBoxIsAtClickPoint(40, 0);
336     assertEquals(vpranges.getStartSeq(), 0);
337     assertEquals(vpranges.getStartRes(),
338             Math.round((float) 40 * alwidth / od.getWidth())
339                     - (lastHiddenCol + 1));
340
341     // click to right of hidden columns such that box runs over right hand side
342     // of alignment
343     // box position is adjusted away from the edge
344     // overly large boxX value reset to width-boxWidth
345     xpos = 100;
346     mouseClick(od, xpos, 5);
347     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
348     assertEquals(od.getBoxY(), 5);
349     assertEquals(od.getBoxWidth(), boxWidth);
350     assertEquals(od.getBoxHeight(), boxHeight);
351     assertEquals(vpranges.getStartRes(),
352             Math.round((float) od.getBoxX() * alwidth / od.getWidth())
353                     - (lastHiddenCol + 1));
354     assertEquals(
355             vpranges.getStartSeq(),
356             Math.round((float) od.getBoxY() * alheight
357                     / od.getSequencesHeight()));
358   }
359
360   /**
361    * Test setting of the box position, when there are hidden cols in the middle
362    * of the alignment
363    */
364   @Test(groups = { "Functional" })
365   public void testFromMouseWithHiddenColsInMiddle()
366   {
367     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
368     assertEquals(od.getBoxX(), 0);
369     assertEquals(od.getBoxY(), 0);
370     assertEquals(od.getBoxWidth(), boxWidth);
371     assertEquals(vpranges.getStartRes(), 0);
372     assertEquals(vpranges.getStartSeq(), 0);
373     
374     // hide columns 63-73, no change to box position or dimensions
375     int firstHidden = 63;
376     int lastHidden = 73;
377     hiddenCols.hideColumns(firstHidden, lastHidden);
378
379     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
380     assertEquals(od.getBoxX(), 0);
381     assertEquals(od.getBoxY(), 0);
382     assertEquals(od.getBoxWidth(), boxWidth);
383     assertEquals(vpranges.getStartRes(), 0);
384     assertEquals(vpranges.getStartSeq(), 0);
385
386     // move box so that it overlaps with hidden cols on one side
387     // box width changes, boxX and scrollCol as for unhidden case
388     int xpos = 55 - boxWidth; // 55 is position in overview approx halfway
389                               // between cols 60 and 70
390     mouseClick(od, xpos, 0);
391     assertEquals(od.getBoxX(), xpos);
392     assertEquals(od.getBoxY(), 0);
393     assertEquals(
394             od.getBoxWidth(),
395             Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
396                     * od.getWidth() / alwidth));
397     assertEquals(od.getBoxHeight(), boxHeight);
398     assertEquals(vpranges.getStartRes(),
399             Math.round(xpos * alwidth / od.getWidth()));
400     assertEquals(vpranges.getStartSeq(), 0);
401
402     // move box so that it completely covers hidden cols
403     // box width changes, boxX and scrollCol as for hidden case
404     xpos = 33;
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(vpranges.getStartRes(),
414             Math.round((float) xpos * alwidth / od.getWidth()));
415     assertEquals(vpranges.getStartSeq(), 0);
416
417     // move box so boxX is in hidden cols, box overhangs at right
418     // boxX and scrollCol at left of hidden area, box width extends across
419     // hidden region
420     xpos = 50;
421     mouseClick(od, xpos, 0);
422     assertEquals(od.getBoxX(),
423             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth));
424     assertEquals(od.getBoxY(), 0);
425     assertEquals(
426             od.getBoxWidth(),
427             boxWidth
428                     + Math.round((float) (lastHidden - firstHidden + 1)
429                             * od.getWidth() / alwidth));
430     assertEquals(od.getBoxHeight(), boxHeight);
431     assertEquals(vpranges.getStartRes(), firstHidden - 1);
432     assertEquals(vpranges.getStartSeq(), 0);
433
434     // move box so boxX is to right of hidden cols, but does not go beyond full
435     // width of alignment
436     // box width, boxX and scrollCol all as for non-hidden case
437     xpos = 75;
438     testBoxIsAtClickPoint(xpos, 0);
439     assertEquals(vpranges.getStartSeq(), 0);
440     assertEquals(vpranges.getStartRes(),
441             Math.round(xpos * alwidth / od.getWidth())
442                     - (lastHidden - firstHidden + 1));
443     
444     // move box so it goes beyond full width of alignment
445     // boxX, scrollCol adjusted back, box width normal
446     xpos = 3000;
447     mouseClick(od, xpos, 5);
448     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
449     assertEquals(od.getBoxY(), 5);
450     assertEquals(od.getBoxWidth(), boxWidth);
451     assertEquals(od.getBoxHeight(), boxHeight);
452     assertEquals(
453             vpranges.getStartRes(),
454             Math.round(((float) od.getBoxX() * alwidth / od.getWidth())
455                     - (lastHidden - firstHidden + 1)));
456     assertEquals(
457             vpranges.getStartSeq(),
458             Math.round((float) od.getBoxY() * alheight
459                     / od.getSequencesHeight()));
460
461   }
462
463   /**
464    * Test setting of the box position, when there are hidden cols at the end of
465    * the alignment
466    */
467   @Test(groups = { "Functional" })
468   public void testFromMouseWithHiddenColsAtEnd()
469   {
470     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
471     assertEquals(od.getBoxX(), 0);
472     assertEquals(od.getBoxY(), 0);
473     assertEquals(od.getBoxWidth(), boxWidth);
474     assertEquals(vpranges.getStartRes(), 0);
475     assertEquals(vpranges.getStartSeq(), 0);
476
477     // hide columns 140-164, no change to box position or dimensions
478     int firstHidden = 140;
479     int lastHidden = 164;
480     hiddenCols.hideColumns(firstHidden, lastHidden);
481     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
482     assertEquals(od.getBoxX(), 0);
483     assertEquals(od.getBoxY(), 0);
484     assertEquals(od.getBoxWidth(), boxWidth);
485     assertEquals(vpranges.getStartRes(), 0);
486     assertEquals(vpranges.getStartSeq(), 0);
487
488     // click to left of hidden cols, without overlapping
489     // boxX, scrollCol and width as normal
490     int xpos = 5;
491     testBoxIsAtClickPoint(xpos, 0);
492     assertEquals(vpranges.getStartSeq(), 0);
493     assertEquals(vpranges.getStartRes(),
494             Math.round((float) xpos * alwidth / od.getWidth()));
495
496     // click to left of hidden cols, with overlap
497     // boxX and scrollCol adjusted for hidden cols, width normal
498     xpos = Math.round((float) 145 * od.getWidth() / alwidth) - boxWidth;
499     mouseClick(od, xpos, 0);
500     assertEquals(od.getBoxX(),
501             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
502                     - boxWidth + 1);
503     assertEquals(od.getBoxY(), 0);
504     assertEquals(od.getBoxWidth(), boxWidth);
505     assertEquals(od.getBoxHeight(), boxHeight);
506     assertEquals(vpranges.getStartRes(),
507             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
508     assertEquals(vpranges.getStartSeq(), 0);
509
510     // click in hidden cols
511     // boxX and scrollCol adjusted for hidden cols, width normal
512     xpos = 115;
513     assertEquals(od.getBoxX(),
514             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
515                     - boxWidth + 1);
516     assertEquals(od.getBoxY(), 0);
517     assertEquals(od.getBoxWidth(), boxWidth);
518     assertEquals(od.getBoxHeight(), boxHeight);
519     assertEquals(vpranges.getStartRes(),
520             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
521     assertEquals(vpranges.getStartSeq(), 0);
522
523     // click off end of alignment
524     // boxX and scrollCol adjusted for hidden cols, width normal
525     xpos = 3000;
526     assertEquals(od.getBoxX(),
527             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
528                     - boxWidth + 1);
529     assertEquals(od.getBoxY(), 0);
530     assertEquals(od.getBoxWidth(), boxWidth);
531     assertEquals(od.getBoxHeight(), boxHeight);
532     assertEquals(vpranges.getStartRes(),
533             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
534     assertEquals(vpranges.getStartSeq(), 0);
535   }
536
537   /**
538    * Test that the box position is set correctly when set from the viewport,
539    * with no hidden rows or columns
540    */
541   @Test(groups = { "Functional" })
542   public void testSetBoxFromViewport()
543   {
544     // move viewport to start of alignment
545     moveViewport(0, 0);
546     assertEquals(od.getBoxX(), 0);
547     assertEquals(od.getBoxY(), 0);
548     assertEquals(od.getBoxWidth(), boxWidth);
549     assertEquals(od.getBoxHeight(), boxHeight);
550
551     // move viewport to right
552     moveViewportH(70);
553     assertEquals(od.getBoxX(),
554             Math.round((float) 70 * od.getWidth() / alwidth));
555     assertEquals(od.getBoxY(), 0);
556     assertEquals(od.getBoxWidth(), boxWidth);
557     assertEquals(od.getBoxHeight(), boxHeight);
558
559     // move viewport down
560     moveViewportV(100);
561     assertEquals(od.getBoxX(),
562             Math.round((float) 70 * od.getWidth() / alwidth));
563     assertEquals(od.getBoxY(),
564             Math.round(100 * od.getSequencesHeight() / alheight));
565     assertEquals(od.getBoxWidth(), boxWidth);
566     assertEquals(od.getBoxHeight(), boxHeight);
567
568     // move viewport to bottom right
569     moveViewport(98, 508);
570     assertEquals(od.getBoxX(),
571             Math.round((float) 98 * od.getWidth() / alwidth));
572     assertEquals(od.getBoxY(),
573             Math.round((float) 508 * od.getSequencesHeight() / alheight));
574     assertEquals(od.getBoxWidth(), boxWidth);
575     assertEquals(od.getBoxHeight(), boxHeight);
576   }
577
578   /**
579    * Test that the box position is set correctly when there are hidden columns
580    * at the start
581    */
582   @Test(groups = { "Functional" })
583   public void testSetBoxFromViewportHiddenColsAtStart()
584   {
585     int firstHidden = 0;
586     int lastHidden = 20;
587     hiddenCols.hideColumns(firstHidden, lastHidden);
588
589     // move viewport to start of alignment
590     moveViewport(0, 0);
591     assertEquals(od.getBoxX(),
592             Math.round((float) (lastHidden + 1) * od.getWidth() / alwidth));
593     assertEquals(od.getBoxY(), 0);
594     assertEquals(od.getBoxWidth(), boxWidth);
595     assertEquals(od.getBoxHeight(), boxHeight);
596
597     // move viewport to end of alignment - need to make startRes by removing
598     // hidden cols because of how viewport/overview are implemented
599     moveViewport(98 - lastHidden - 1, 0);
600     assertEquals(od.getBoxX(),
601             Math.round((float) 98 * od.getWidth() / alwidth));
602     assertEquals(od.getBoxY(), 0);
603     assertEquals(od.getBoxWidth(), boxWidth);
604     assertEquals(od.getBoxHeight(), boxHeight);
605   }
606
607   /**
608    * Test that the box position is set correctly when there are hidden columns
609    * in the middle
610    */
611   @Test(groups = { "Functional" })
612   public void testSetBoxFromViewportHiddenColsInMiddle()
613   {
614     int firstHidden = 68;
615     int lastHidden = 78;
616     hiddenCols.hideColumns(firstHidden, lastHidden);
617
618     // move viewport before hidden columns
619     moveViewport(3, 0);
620
621     assertEquals(od.getBoxX(),
622             Math.round((float) 3 * od.getWidth() / alwidth));
623     assertEquals(od.getBoxY(), 0);
624     assertEquals(od.getBoxWidth(), boxWidth);
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     // viewport can't actually extend into hidden cols,
682     // so move to the far right edge of the viewport
683     moveViewport(firstHidden - viewWidth, 0);
684     assertEquals(od.getBoxX(),
685             Math.round((float) (firstHidden - viewWidth)
686                     * od.getWidth() / alwidth));
687     assertEquals(od.getBoxY(), 0);
688     assertEquals(od.getBoxWidth(), boxWidth);
689     assertEquals(od.getBoxHeight(), boxHeight);
690   }
691
692   /**
693    * Test that the box position is set correctly when there are hidden rows at
694    * the start
695    */
696   @Test(groups = { "Functional" })
697   public void testSetBoxFromViewportHiddenRowsAtStart()
698   {
699     int firstHidden = 0;
700     int lastHidden = 20;
701     hideSequences(firstHidden, lastHidden);
702
703     // move viewport to start of alignment:
704     // box moves to below hidden rows, height remains same
705     moveViewport(0, 0);
706     assertEquals(od.getBoxX(), 0);
707     assertEquals(od.getBoxY(),
708             Math.round((float) (lastHidden + 1) * od.getSequencesHeight()
709                     / alheight));
710     assertEquals(od.getBoxWidth(), boxWidth);
711     assertEquals(od.getBoxHeight(), boxHeight);
712
713     // move viewport to end of alignment
714     moveViewport(0, 525 - viewHeight - lastHidden - 1);
715     assertEquals(od.getBoxX(), 0);
716     assertEquals(
717             od.getBoxY(),
718             Math.round((float) (525 - viewHeight) * od.getSequencesHeight()
719                     / alheight));
720     assertEquals(od.getBoxWidth(), boxWidth);
721     assertEquals(od.getBoxHeight(), boxHeight);
722   }
723
724   /**
725    * Test that the box position is set correctly when there are hidden rows in
726    * the middle
727    */
728   @Test(groups = { "Functional" })
729   public void testSetBoxFromViewportHiddenRowsInMiddle()
730   {
731     int firstHidden = 200;
732     int lastHidden = 210;
733     hideSequences(firstHidden, lastHidden);
734
735     // move viewport to start of alignment:
736     // box, height etc as in non-hidden case
737     moveViewport(0, 0);
738     assertEquals(od.getBoxX(), 0);
739     assertEquals(od.getBoxY(), 0);
740     assertEquals(od.getBoxWidth(), boxWidth);
741     assertEquals(od.getBoxHeight(), boxHeight);
742
743     // move viewport to straddle hidden rows
744     moveViewport(0, 198);
745     assertEquals(od.getBoxX(), 0);
746     assertEquals(od.getBoxY(), Math.round ((float)198 * od.getSequencesHeight()
747             / alheight));
748     assertEquals(od.getBoxWidth(), boxWidth);
749     assertEquals(
750             od.getBoxHeight(),
751             Math.round((float) (viewHeight + lastHidden - firstHidden + 1)
752                     * od.getSequencesHeight() / alheight));
753   }
754
755   /**
756    * Test that the box position is set correctly when there are hidden rows at
757    * the bottom
758    */
759   @Test(groups = { "Functional" })
760   public void testSetBoxFromViewportHiddenRowsAtEnd()
761   {
762     int firstHidden = 500;
763     int lastHidden = 524;
764     hideSequences(firstHidden, lastHidden);
765
766     // move viewport to start of alignment:
767     // box, height etc as in non-hidden case
768     moveViewport(0, 0);
769     assertEquals(od.getBoxX(), 0);
770     assertEquals(od.getBoxY(), 0);
771     assertEquals(od.getBoxWidth(), boxWidth);
772     assertEquals(od.getBoxHeight(), boxHeight);
773
774     // move viewport to end of alignment
775     // viewport sits above hidden rows and does not include them
776     moveViewport(0, firstHidden - viewHeight - 1);
777     assertEquals(od.getBoxX(), 0);
778     assertEquals(
779             od.getBoxY(),
780             Math.round((float) (firstHidden - viewHeight - 1)
781                     * od.getSequencesHeight() / alheight));
782     assertEquals(od.getBoxWidth(), boxWidth);
783     assertEquals(od.getBoxHeight(), boxHeight);
784
785   }
786
787   /**
788    * Test setting of the box position, when there are hidden rows at the start
789    * of the alignment
790    */
791   @Test(groups = { "Functional" })
792   public void testFromMouseWithHiddenRowsAtStart()
793   {
794     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
795     assertEquals(od.getBoxX(), 0);
796     assertEquals(od.getBoxY(), 0);
797     assertEquals(od.getBoxHeight(), boxHeight);
798     assertEquals(od.getBoxWidth(), boxWidth);
799     assertEquals(vpranges.getStartRes(), 0);
800     assertEquals(vpranges.getStartSeq(), 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);
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
842     assertEquals(od.getBoxX(), 0);
843     assertEquals(od.getBoxY(), 0);
844     assertEquals(od.getBoxWidth(), boxWidth);
845     assertEquals(od.getBoxHeight(), boxHeight);
846     assertEquals(vpranges.getStartRes(), 0);
847     assertEquals(vpranges.getStartSeq(), 0);
848
849     // hide rows in middle and check updated box position is correct
850     // no changes
851     int firstHiddenRow = 50;
852     int lastHiddenRow = 54;
853     hideSequences(firstHiddenRow, lastHiddenRow);
854
855     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
856
857     assertEquals(od.getBoxX(), 0);
858     assertEquals(od.getBoxY(), 0);
859     assertEquals(od.getBoxWidth(), boxWidth);
860     assertEquals(od.getBoxHeight(), boxHeight);
861
862     // click above hidden rows, so that box overlaps
863     int ypos = 35; // column value in residues
864     mouseClick(od, 0,
865             Math.round((float) ypos * od.getSequencesHeight() / alheight));
866     assertEquals(od.getBoxX(), 0);
867     assertEquals(od.getBoxY(),
868             Math.round((float) ypos * od.getSequencesHeight() / alheight));
869     assertEquals(od.getBoxWidth(), boxWidth);
870     assertEquals(
871             od.getBoxHeight(),
872             boxHeight
873                     + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
874                             * od.getSequencesHeight() / alheight));
875
876     // click so that box straddles hidden rows
877     ypos = 44; // column value in residues
878     mouseClick(od, 0,
879             Math.round((float) ypos * od.getSequencesHeight() / alheight));
880     assertEquals(od.getBoxX(), 0);
881     assertEquals(od.getBoxY(),
882             Math.round((float) ypos * od.getSequencesHeight() / alheight));
883     assertEquals(od.getBoxWidth(), boxWidth);
884     assertEquals(
885             od.getBoxHeight(),
886             boxHeight
887                     + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
888                             * od.getSequencesHeight() / alheight));
889   }
890
891   /**
892    * Test setting of the box position, when there are hidden rows at the end of
893    * the alignment
894    */
895   @Test(groups = { "Functional" })
896   public void testFromMouseWithHiddenRowsAtEnd()
897   {
898     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
899     assertEquals(od.getBoxX(), 0);
900     assertEquals(od.getBoxY(), 0);
901     assertEquals(od.getBoxWidth(), boxWidth);
902     assertEquals(od.getBoxHeight(), boxHeight);
903     assertEquals(vpranges.getStartRes(), 0);
904     assertEquals(vpranges.getStartSeq(), 0);
905
906     // hide rows at end and check updated box position is correct
907     // no changes
908     int firstHidden = 500;
909     int lastHidden = 524;
910     hideSequences(firstHidden, lastHidden);
911
912     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
913     assertEquals(od.getBoxX(), 0);
914     assertEquals(od.getBoxY(), 0);
915     assertEquals(od.getBoxWidth(), boxWidth);
916     assertEquals(od.getBoxHeight(), boxHeight);
917
918     // click above hidden rows
919     int ypos = 40; // row 40
920     mouseClick(od, 0,
921             Math.round((float) ypos * od.getSequencesHeight() / alheight));
922     assertEquals(od.getBoxX(), 0);
923     assertEquals(od.getBoxY(),
924             Math.round((float) ypos * od.getSequencesHeight() / alheight));
925     assertEquals(od.getBoxWidth(), boxWidth);
926     assertEquals(od.getBoxHeight(), boxHeight);
927
928     // click above hidden rows so box overlaps
929     // boxY moved upwards, boxHeight remains same
930     ypos = 497; // row 497
931     mouseClick(od, 0,
932             Math.round((float) ypos * od.getSequencesHeight() / alheight));
933     assertEquals(od.getBoxX(), 0);
934     assertEquals(
935             od.getBoxY(),
936             Math.round((float) (firstHidden - viewHeight)
937                     * od.getSequencesHeight() / alheight));
938     assertEquals(od.getBoxWidth(), boxWidth);
939     assertEquals(od.getBoxHeight(), boxHeight);
940
941     // click within hidden rows
942     ypos = 505;
943     mouseClick(od, 0,
944             Math.round((float) ypos * od.getSequencesHeight() / alheight));
945     assertEquals(od.getBoxX(), 0);
946     assertEquals(
947             od.getBoxY(),
948             Math.round((firstHidden - viewHeight) * od.getSequencesHeight()
949                     / alheight));
950     assertEquals(od.getBoxWidth(), boxWidth);
951     assertEquals(od.getBoxHeight(), boxHeight);
952   }
953
954   /*
955    * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
956    */
957   private void moveViewportH(int startRes)
958   {
959     vpranges.setViewportStartAndWidth(startRes, viewWidth);
960     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
961   }
962
963   /*
964    * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
965    */
966   private void moveViewportV(int startSeq)
967   {
968     vpranges.setViewportStartAndHeight(startSeq, viewHeight);
969     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
970   }
971
972   /*
973    * Move viewport horizontally and vertically.
974    */
975   private void moveViewport(int startRes, int startSeq)
976   {
977     vpranges.setViewportStartAndWidth(startRes, viewWidth);
978     vpranges.setViewportStartAndHeight(startSeq, viewHeight);
979     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
980   }
981
982   /*
983    * Mouse click as position x,y in overview window
984    */
985   private void mouseClick(OverviewDimensions od, int x, int y)
986   {
987     od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols);
988
989     // updates require an OverviewPanel to exist which it doesn't here
990     // so call setBoxPosition() as it would be called by the AlignmentPanel
991     // normally
992     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
993   }
994   
995   /*
996    * Test that the box is positioned with the top left corner at xpos, ypos
997    * and with the original width and height
998    */
999   private void testBoxIsAtClickPoint(int xpos, int ypos)
1000   {
1001     mouseClick(od, xpos, ypos);
1002     assertEquals(od.getBoxX(), xpos);
1003     assertEquals(od.getBoxY(), ypos);
1004     assertEquals(od.getBoxWidth(), boxWidth);
1005     assertEquals(od.getBoxHeight(), boxHeight);
1006
1007   }
1008
1009   /*
1010    * Hide sequences between start and end
1011    */
1012   private void hideSequences(int start, int end)
1013   {
1014     SequenceI[] allseqs = al.getSequencesArray();
1015     SequenceGroup theseSeqs = new SequenceGroup();
1016     
1017     for (int i = start; i <= end; i++)
1018     {
1019       theseSeqs.addSequence(allseqs[i], false);
1020       al.getHiddenSequences().hideSequence(allseqs[i]);
1021     }
1022
1023     hiddenRepSequences.put(allseqs[start], theseSeqs);
1024   }
1025
1026   /**
1027    * Test setting of the box position, when there are hidden rows at the start
1028    * of the alignment
1029    */
1030   @Test(groups = { "Functional" })
1031   public void testFromMouseWithHiddenRowsAtStartWrapped()
1032   {
1033     vpranges.setWrappedMode(true);
1034     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
1035     assertEquals(od.getBoxX(), 0);
1036     assertEquals(od.getBoxY(), 0);
1037     assertEquals(od.getBoxHeight(), boxHeight);
1038     assertEquals(od.getBoxWidth(), boxWidth);
1039     assertEquals(vpranges.getStartRes(), 0);
1040     assertEquals(vpranges.getStartSeq(), 0);
1041   
1042     // hide rows at start and check updated box position is correct
1043     // changes boxY but not boxheight
1044     int lastHiddenRow = 30;
1045     hideSequences(0, lastHiddenRow);
1046   
1047     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
1048     assertEquals(od.getBoxX(), 0);
1049     assertEquals(od.getBoxY(),
1050             Math.round((float) (lastHiddenRow + 1)
1051                     * od.getSequencesHeight() / alheight));
1052     assertEquals(od.getBoxWidth(), boxWidth);
1053     assertEquals(od.getBoxHeight(), boxHeight);
1054   
1055     // click in hidden rows - same result
1056     mouseClick(od, 0, 0);
1057     assertEquals(od.getBoxX(), 0);
1058     int boxY = od.getBoxY();
1059     assertEquals(
1060             boxY,
1061             Math.round((float) (lastHiddenRow + 1)
1062                     * od.getSequencesHeight() / alheight));
1063     assertEquals(od.getBoxWidth(), boxWidth);
1064     assertEquals(od.getBoxHeight(), boxHeight);
1065   
1066     // click below hidden rows
1067     // vertical move of overview box is suppressed in wrapped mode
1068     mouseClick(od, 0, 150);
1069     assertEquals(od.getBoxX(), 0);
1070     assertEquals(od.getBoxY(), boxY); // unchanged
1071     assertEquals(od.getBoxWidth(), boxWidth);
1072     assertEquals(od.getBoxHeight(), boxHeight);
1073   }
1074 }