fef754844765be8527f17a5c27f04b061f5e84b8
[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<>();
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() + vpranges.getViewportHeight() / 2,
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(), 0);
222     assertEquals(vpranges.getStartSeq(), 0);
223
224     // overly large boxX value reset to width-boxWidth
225     mouseClick(od, 101, 6);
226     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
227     assertEquals(od.getBoxY(), 1);
228     assertEquals(od.getBoxWidth(), boxWidth);
229     assertEquals(od.getBoxHeight(), boxHeight);
230     assertEquals(vpranges.getStartRes(),
231             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
232     assertEquals(
233             vpranges.getStartSeq(),
234             Math.round((float) od.getBoxY() * alheight
235                     / od.getSequencesHeight()));
236
237     // overly large boxY value reset to sequenceHeight - boxHeight
238     mouseClick(od, 10, 520);
239     assertEquals(od.getBoxX(), 10);
240     assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight());
241     assertEquals(od.getBoxWidth(), boxWidth);
242     assertEquals(od.getBoxHeight(), boxHeight);
243     assertEquals(vpranges.getStartRes() + vpranges.getViewportWidth() / 2,
244             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
245
246     // here (float) od.getBoxY() * alheight / od.getSequencesHeight() = 507.5
247     // and round rounds to 508; however we get 507 working with row values
248     // hence the subtraction of 1
249     assertEquals(
250             vpranges.getStartSeq() + vpranges.getViewportWidth() / 2,
251             Math.round((float) od.getBoxY() * alheight
252                     / od.getSequencesHeight()) - 1);
253
254     // click past end of alignment, as above
255     mouseClick(od, 3000, 5);
256     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
257     assertEquals(od.getBoxWidth(), boxWidth);
258     assertEquals(od.getBoxHeight(), boxHeight);
259     assertEquals(vpranges.getStartRes() + vpranges.getViewportWidth() / 2,
260             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
261     assertEquals(
262             vpranges.getStartSeq() + vpranges.getViewportHeight() / 2,
263             Math.round((float) od.getBoxY() * alheight
264                     / od.getSequencesHeight()));
265
266     // move viewport so startRes non-zero and then mouseclick
267     moveViewportH(50);
268
269     // click at viewport position
270     int oldboxx = od.getBoxX();
271     int oldboxy = od.getBoxY();
272     mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2);
273     assertEquals(od.getBoxX(), oldboxx + 5);
274     assertEquals(od.getBoxWidth(), boxWidth);
275     assertEquals(od.getBoxHeight(), boxHeight);
276     assertEquals(vpranges.getStartRes() + vpranges.getViewportWidth() / 2,
277             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
278     assertEquals(od.getBoxY(), oldboxy + 2);
279     assertEquals(
280             vpranges.getStartSeq() + vpranges.getViewportHeight() / 2,
281             Math.round((float) od.getBoxY() * alheight
282                     / od.getSequencesHeight()));
283
284     // click at top corner
285     mouseClick(od, 0, 0);
286     assertEquals(od.getBoxX(), 0);
287     assertEquals(vpranges.getStartRes(), 0);
288     assertEquals(od.getBoxY(), 0);
289     assertEquals(vpranges.getStartSeq(), 0);
290     assertEquals(od.getBoxWidth(), boxWidth);
291     assertEquals(od.getBoxHeight(), boxHeight);
292   }
293
294   /**
295    * Test setting of the box position, when there are hidden cols at the start
296    * of the alignment
297    */
298   @Test(groups = { "Functional" })
299   public void testFromMouseWithHiddenColsAtStart()
300   {
301     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
302     assertEquals(od.getBoxX(), 0);
303     assertEquals(od.getBoxY(), 0);
304     assertEquals(od.getBoxWidth(), boxWidth);
305     assertEquals(vpranges.getStartRes(), 0);
306     assertEquals(vpranges.getStartSeq(), 0);
307
308     // hide cols at start and check updated box position is correct
309     // changes boxX but not boxwidth
310     int lastHiddenCol = 30;
311     hiddenCols.hideColumns(0, lastHiddenCol);
312
313     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
314     assertEquals(od.getBoxX(),
315             Math.round((float) (lastHiddenCol + 1) * od.getWidth()
316                     / alwidth));
317     assertEquals(od.getBoxWidth(), boxWidth);
318     assertEquals(od.getBoxHeight(), boxHeight);
319
320     // try to click in hidden cols, check box does not move
321     int xpos = 10;
322     mouseClick(od, xpos, 0);
323     assertEquals(
324             od.getBoxX(),
325             Math.round((float) (lastHiddenCol + 1) * od.getWidth()
326                     / alwidth));
327     assertEquals(od.getBoxY(), 0);
328     assertEquals(od.getBoxWidth(), boxWidth);
329     assertEquals(od.getBoxHeight(), boxHeight);
330     assertEquals(vpranges.getStartSeq(), 0);
331     assertEquals(vpranges.getStartRes(), 0);
332
333     // click to right of hidden columns, box moves to click point
334     testBoxIsAtClickPoint(40, 0);
335     assertEquals(vpranges.getStartSeq(), 0);
336     assertEquals(vpranges.getStartRes(),
337             Math.round((float) 40 * alwidth / od.getWidth())
338                     - (lastHiddenCol + 1));
339
340     // click to right of hidden columns such that box runs over right hand side
341     // of alignment
342     // box position is adjusted away from the edge
343     // overly large boxX value reset to width-boxWidth
344     xpos = 100;
345     mouseClick(od, xpos, 5);
346     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
347     assertEquals(od.getBoxY(), 5);
348     assertEquals(od.getBoxWidth(), boxWidth);
349     assertEquals(od.getBoxHeight(), boxHeight);
350     assertEquals(vpranges.getStartRes(),
351             Math.round((float) od.getBoxX() * alwidth / od.getWidth())
352                     - (lastHiddenCol + 1));
353     assertEquals(
354             vpranges.getStartSeq(),
355             Math.round((float) od.getBoxY() * alheight
356                     / od.getSequencesHeight()));
357   }
358
359   /**
360    * Test setting of the box position, when there are hidden cols in the middle
361    * of the alignment
362    */
363   @Test(groups = { "Functional" })
364   public void testFromMouseWithHiddenColsInMiddle()
365   {
366     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
367     assertEquals(od.getBoxX(), 0);
368     assertEquals(od.getBoxY(), 0);
369     assertEquals(od.getBoxWidth(), boxWidth);
370     assertEquals(vpranges.getStartRes(), 0);
371     assertEquals(vpranges.getStartSeq(), 0);
372     
373     // hide columns 63-73, no change to box position or dimensions
374     int firstHidden = 63;
375     int lastHidden = 73;
376     hiddenCols.hideColumns(firstHidden, lastHidden);
377
378     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
379     assertEquals(od.getBoxX(), 0);
380     assertEquals(od.getBoxY(), 0);
381     assertEquals(od.getBoxWidth(), boxWidth);
382     assertEquals(vpranges.getStartRes(), 0);
383     assertEquals(vpranges.getStartSeq(), 0);
384
385     // move box so that it overlaps with hidden cols on one side
386     // box width changes, boxX and scrollCol as for unhidden case
387     int xpos = 55 - boxWidth; // 55 is position in overview approx halfway
388                               // between cols 60 and 70
389     mouseClick(od, xpos, 0);
390     assertEquals(od.getBoxX(), xpos);
391     assertEquals(od.getBoxY(), 0);
392     assertEquals(
393             od.getBoxWidth(),
394             Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
395                     * od.getWidth() / alwidth));
396     assertEquals(od.getBoxHeight(), boxHeight);
397     assertEquals(vpranges.getStartRes(),
398             Math.round(xpos * alwidth / od.getWidth()));
399     assertEquals(vpranges.getStartSeq(), 0);
400
401     // move box so that it completely covers hidden cols
402     // box width changes, boxX and scrollCol as for hidden case
403     xpos = 33;
404     mouseClick(od, xpos, 0);
405     assertEquals(od.getBoxX(), xpos);
406     assertEquals(od.getBoxY(), 0);
407     assertEquals(
408             od.getBoxWidth(),
409             Math.round(boxWidth + (float) (lastHidden - firstHidden + 1)
410                     * od.getWidth() / alwidth));
411     assertEquals(od.getBoxHeight(), boxHeight);
412     assertEquals(vpranges.getStartRes(),
413             Math.round((float) xpos * alwidth / od.getWidth()));
414     assertEquals(vpranges.getStartSeq(), 0);
415
416     // move box so boxX is in hidden cols, box overhangs at right
417     // boxX and scrollCol at left of hidden area, box width extends across
418     // hidden region
419     xpos = 50;
420     mouseClick(od, xpos, 0);
421     assertEquals(od.getBoxX(),
422             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth));
423     assertEquals(od.getBoxY(), 0);
424     assertEquals(
425             od.getBoxWidth(),
426             boxWidth
427                     + Math.round((float) (lastHidden - firstHidden + 1)
428                             * od.getWidth() / alwidth));
429     assertEquals(od.getBoxHeight(), boxHeight);
430     assertEquals(vpranges.getStartRes(), firstHidden - 1);
431     assertEquals(vpranges.getStartSeq(), 0);
432
433     // move box so boxX is to right of hidden cols, but does not go beyond full
434     // width of alignment
435     // box width, boxX and scrollCol all as for non-hidden case
436     xpos = 75;
437     testBoxIsAtClickPoint(xpos, 0);
438     assertEquals(vpranges.getStartSeq(), 0);
439     assertEquals(vpranges.getStartRes(),
440             Math.round(xpos * alwidth / od.getWidth())
441                     - (lastHidden - firstHidden + 1));
442     
443     // move box so it goes beyond full width of alignment
444     // boxX, scrollCol adjusted back, box width normal
445     xpos = 3000;
446     mouseClick(od, xpos, 5);
447     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
448     assertEquals(od.getBoxY(), 5);
449     assertEquals(od.getBoxWidth(), boxWidth);
450     assertEquals(od.getBoxHeight(), boxHeight);
451     assertEquals(
452             vpranges.getStartRes(),
453             Math.round(((float) od.getBoxX() * alwidth / od.getWidth())
454                     - (lastHidden - firstHidden + 1)));
455     assertEquals(
456             vpranges.getStartSeq(),
457             Math.round((float) od.getBoxY() * alheight
458                     / od.getSequencesHeight()));
459
460   }
461
462   /**
463    * Test setting of the box position, when there are hidden cols at the end of
464    * the alignment
465    */
466   @Test(groups = { "Functional" })
467   public void testFromMouseWithHiddenColsAtEnd()
468   {
469     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
470     assertEquals(od.getBoxX(), 0);
471     assertEquals(od.getBoxY(), 0);
472     assertEquals(od.getBoxWidth(), boxWidth);
473     assertEquals(vpranges.getStartRes(), 0);
474     assertEquals(vpranges.getStartSeq(), 0);
475
476     // hide columns 140-164, no change to box position or dimensions
477     int firstHidden = 140;
478     int lastHidden = 164;
479     hiddenCols.hideColumns(firstHidden, lastHidden);
480     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
481     assertEquals(od.getBoxX(), 0);
482     assertEquals(od.getBoxY(), 0);
483     assertEquals(od.getBoxWidth(), boxWidth);
484     assertEquals(vpranges.getStartRes(), 0);
485     assertEquals(vpranges.getStartSeq(), 0);
486
487     // click to left of hidden cols, without overlapping
488     // boxX, scrollCol and width as normal
489     int xpos = 5;
490     testBoxIsAtClickPoint(xpos, 0);
491     assertEquals(vpranges.getStartSeq(), 0);
492     assertEquals(vpranges.getStartRes(),
493             Math.round((float) xpos * alwidth / od.getWidth()));
494
495     // click to left of hidden cols, with overlap
496     // boxX and scrollCol adjusted for hidden cols, width normal
497     xpos = Math.round((float) 145 * od.getWidth() / alwidth) - boxWidth;
498     mouseClick(od, xpos, 0);
499     assertEquals(od.getBoxX(),
500             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
501                     - boxWidth + 1);
502     assertEquals(od.getBoxY(), 0);
503     assertEquals(od.getBoxWidth(), boxWidth);
504     assertEquals(od.getBoxHeight(), boxHeight);
505     assertEquals(vpranges.getStartRes(),
506             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
507     assertEquals(vpranges.getStartSeq(), 0);
508
509     // click in hidden cols
510     // boxX and scrollCol adjusted for hidden cols, width normal
511     xpos = 115;
512     assertEquals(od.getBoxX(),
513             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
514                     - boxWidth + 1);
515     assertEquals(od.getBoxY(), 0);
516     assertEquals(od.getBoxWidth(), boxWidth);
517     assertEquals(od.getBoxHeight(), boxHeight);
518     assertEquals(vpranges.getStartRes(),
519             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
520     assertEquals(vpranges.getStartSeq(), 0);
521
522     // click off end of alignment
523     // boxX and scrollCol adjusted for hidden cols, width normal
524     xpos = 3000;
525     assertEquals(od.getBoxX(),
526             Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)
527                     - boxWidth + 1);
528     assertEquals(od.getBoxY(), 0);
529     assertEquals(od.getBoxWidth(), boxWidth);
530     assertEquals(od.getBoxHeight(), boxHeight);
531     assertEquals(vpranges.getStartRes(),
532             Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
533     assertEquals(vpranges.getStartSeq(), 0);
534   }
535
536   /**
537    * Test that the box position is set correctly when set from the viewport,
538    * with no hidden rows or columns
539    */
540   @Test(groups = { "Functional" })
541   public void testSetBoxFromViewport()
542   {
543     // move viewport to start of alignment
544     moveViewport(0, 0);
545     assertEquals(od.getBoxX(), 0);
546     assertEquals(od.getBoxY(), 0);
547     assertEquals(od.getBoxWidth(), boxWidth);
548     assertEquals(od.getBoxHeight(), boxHeight);
549
550     // move viewport to right
551     moveViewportH(70);
552     assertEquals(od.getBoxX(),
553             Math.round((float) 70 * od.getWidth() / alwidth));
554     assertEquals(od.getBoxY(), 0);
555     assertEquals(od.getBoxWidth(), boxWidth);
556     assertEquals(od.getBoxHeight(), boxHeight);
557
558     // move viewport down
559     moveViewportV(100);
560     assertEquals(od.getBoxX(),
561             Math.round((float) 70 * od.getWidth() / alwidth));
562     assertEquals(od.getBoxY(),
563             Math.round(100 * od.getSequencesHeight() / alheight));
564     assertEquals(od.getBoxWidth(), boxWidth);
565     assertEquals(od.getBoxHeight(), boxHeight);
566
567     // move viewport to bottom right
568     moveViewport(98, 508);
569     assertEquals(od.getBoxX(),
570             Math.round((float) 98 * od.getWidth() / alwidth));
571     assertEquals(od.getBoxY(),
572             Math.round((float) 508 * od.getSequencesHeight() / alheight));
573     assertEquals(od.getBoxWidth(), boxWidth);
574     assertEquals(od.getBoxHeight(), boxHeight);
575   }
576
577   /**
578    * Test that the box position is set correctly when there are hidden columns
579    * at the start
580    */
581   @Test(groups = { "Functional" })
582   public void testSetBoxFromViewportHiddenColsAtStart()
583   {
584     int firstHidden = 0;
585     int lastHidden = 20;
586     hiddenCols.hideColumns(firstHidden, lastHidden);
587
588     // move viewport to start of alignment
589     moveViewport(0, 0);
590     assertEquals(od.getBoxX(),
591             Math.round((float) (lastHidden + 1) * od.getWidth() / alwidth));
592     assertEquals(od.getBoxY(), 0);
593     assertEquals(od.getBoxWidth(), boxWidth);
594     assertEquals(od.getBoxHeight(), boxHeight);
595
596     // move viewport to end of alignment - need to make startRes by removing
597     // hidden cols because of how viewport/overview are implemented
598     moveViewport(98 - lastHidden - 1, 0);
599     assertEquals(od.getBoxX(),
600             Math.round((float) 98 * od.getWidth() / alwidth));
601     assertEquals(od.getBoxY(), 0);
602     assertEquals(od.getBoxWidth(), boxWidth);
603     assertEquals(od.getBoxHeight(), boxHeight);
604   }
605
606   /**
607    * Test that the box position is set correctly when there are hidden columns
608    * in the middle
609    */
610   @Test(groups = { "Functional" })
611   public void testSetBoxFromViewportHiddenColsInMiddle()
612   {
613     int firstHidden = 68;
614     int lastHidden = 78;
615     hiddenCols.hideColumns(firstHidden, lastHidden);
616
617     // move viewport before hidden columns
618     moveViewport(3, 0);
619
620     assertEquals(od.getBoxX(),
621             Math.round((float) 3 * od.getWidth() / alwidth));
622     assertEquals(od.getBoxY(), 0);
623     assertEquals(od.getBoxWidth(), boxWidth);
624     assertEquals(od.getBoxHeight(), boxHeight);
625
626     // move viewport to left of hidden columns with overlap
627     moveViewport(10, 0);
628     assertEquals(od.getBoxX(),
629             Math.round((float) 10 * od.getWidth() / alwidth));
630     assertEquals(od.getBoxY(), 0);
631     assertEquals(
632             od.getBoxWidth(),
633             boxWidth
634                     + Math.round((float) (lastHidden - firstHidden + 1)
635                             * od.getWidth() / alwidth));
636     assertEquals(od.getBoxHeight(), boxHeight);
637
638     // move viewport to straddle hidden columns
639     moveViewport(63, 0);
640     assertEquals(od.getBoxX(),
641             Math.round((float) 63 * od.getWidth() / alwidth));
642     assertEquals(od.getBoxY(), 0);
643     assertEquals(
644             od.getBoxWidth(),
645             boxWidth
646                     + Math.round((lastHidden - firstHidden + 1)
647                             * od.getWidth() / alwidth));
648     assertEquals(od.getBoxHeight(), boxHeight);
649
650     // move viewport to right of hidden columns, no overlap
651     moveViewport(80 - (lastHidden - firstHidden + 1), 0);
652     assertEquals(od.getBoxX(),
653             Math.round((float) 80 * od.getWidth() / alwidth));
654     assertEquals(od.getBoxY(), 0);
655     assertEquals(od.getBoxWidth(), boxWidth);
656     assertEquals(od.getBoxHeight(), boxHeight);
657
658   }
659
660   /**
661    * Test that the box position is set correctly when there are hidden columns
662    * at the end
663    */
664   @Test(groups = { "Functional" })
665   public void testSetBoxFromViewportHiddenColsAtEnd()
666   {
667     int firstHidden = 152;
668     int lastHidden = 164;
669     hiddenCols.hideColumns(firstHidden, lastHidden);
670
671     // move viewport before hidden columns
672     moveViewport(3, 0);
673     assertEquals(od.getBoxX(),
674             Math.round((float) 3 * od.getWidth() / alwidth));
675     assertEquals(od.getBoxY(), 0);
676     assertEquals(od.getBoxWidth(), boxWidth);
677     assertEquals(od.getBoxHeight(), boxHeight);
678
679     // move viewport to hidden columns
680     // viewport can't actually extend into hidden cols,
681     // so move to the far right edge of the viewport
682     moveViewport(firstHidden - viewWidth, 0);
683     assertEquals(od.getBoxX(),
684             Math.round((float) (firstHidden - viewWidth)
685                     * od.getWidth() / alwidth));
686     assertEquals(od.getBoxY(), 0);
687     assertEquals(od.getBoxWidth(), boxWidth);
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     assertEquals(od.getBoxX(), 0);
795     assertEquals(od.getBoxY(), 0);
796     assertEquals(od.getBoxHeight(), boxHeight);
797     assertEquals(od.getBoxWidth(), boxWidth);
798     assertEquals(vpranges.getStartRes(), 0);
799     assertEquals(vpranges.getStartSeq(), 0);
800
801     // hide rows at start and check updated box position is correct
802     // changes boxY but not boxheight
803     int lastHiddenRow = 30;
804     hideSequences(0, lastHiddenRow);
805
806     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
807     assertEquals(od.getBoxX(), 0);
808     assertEquals(od.getBoxY(),
809             Math.round((float) (lastHiddenRow + 1)
810                     * od.getSequencesHeight() / alheight));
811     assertEquals(od.getBoxWidth(), boxWidth);
812     assertEquals(od.getBoxHeight(), boxHeight);
813
814     // click in hidden rows - same result
815     mouseClick(od, 0, 0);
816     assertEquals(od.getBoxX(), 0);
817     assertEquals(
818             od.getBoxY(),
819             Math.round((float) (lastHiddenRow + 1)
820                     * od.getSequencesHeight() / alheight));
821     assertEquals(od.getBoxWidth(), boxWidth);
822     assertEquals(od.getBoxHeight(), boxHeight);
823
824     // click below hidden rows
825     mouseClick(od, 0, 150);
826     assertEquals(od.getBoxX(), 0);
827     assertEquals(od.getBoxY(), 150);
828     assertEquals(od.getBoxWidth(), boxWidth);
829     assertEquals(od.getBoxHeight(), boxHeight);
830   }
831
832   /**
833    * Test setting of the box position, when there are hidden rows at the middle
834    * of the alignment
835    */
836   @Test(groups = { "Functional" })
837   public void testFromMouseWithHiddenRowsInMiddle()
838   {
839     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
840
841     assertEquals(od.getBoxX(), 0);
842     assertEquals(od.getBoxY(), 0);
843     assertEquals(od.getBoxWidth(), boxWidth);
844     assertEquals(od.getBoxHeight(), boxHeight);
845     assertEquals(vpranges.getStartRes(), 0);
846     assertEquals(vpranges.getStartSeq(), 0);
847
848     // hide rows in middle and check updated box position is correct
849     // no changes
850     int firstHiddenRow = 50;
851     int lastHiddenRow = 54;
852     hideSequences(firstHiddenRow, lastHiddenRow);
853
854     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
855
856     assertEquals(od.getBoxX(), 0);
857     assertEquals(od.getBoxY(), 0);
858     assertEquals(od.getBoxWidth(), boxWidth);
859     assertEquals(od.getBoxHeight(), boxHeight);
860
861     // click above hidden rows, so that box overlaps
862     int ypos = 35; // column value in residues
863     mouseClick(od, 0,
864             Math.round((float) ypos * od.getSequencesHeight() / alheight));
865     assertEquals(od.getBoxX(), 0);
866     assertEquals(od.getBoxY(),
867             Math.round((float) ypos * od.getSequencesHeight() / alheight));
868     assertEquals(od.getBoxWidth(), boxWidth);
869     assertEquals(
870             od.getBoxHeight(),
871             boxHeight
872                     + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
873                             * od.getSequencesHeight() / alheight));
874
875     // click so that box straddles hidden rows
876     ypos = 44; // column value in residues
877     mouseClick(od, 0,
878             Math.round((float) ypos * od.getSequencesHeight() / alheight));
879     assertEquals(od.getBoxX(), 0);
880     assertEquals(od.getBoxY(),
881             Math.round((float) ypos * od.getSequencesHeight() / alheight));
882     assertEquals(od.getBoxWidth(), boxWidth);
883     assertEquals(
884             od.getBoxHeight(),
885             boxHeight
886                     + Math.round((float) (lastHiddenRow - firstHiddenRow + 1)
887                             * od.getSequencesHeight() / alheight));
888   }
889
890   /**
891    * Test setting of the box position, when there are hidden rows at the end of
892    * the alignment
893    */
894   @Test(groups = { "Functional" })
895   public void testFromMouseWithHiddenRowsAtEnd()
896   {
897     od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
898     assertEquals(od.getBoxX(), 0);
899     assertEquals(od.getBoxY(), 0);
900     assertEquals(od.getBoxWidth(), boxWidth);
901     assertEquals(od.getBoxHeight(), boxHeight);
902     assertEquals(vpranges.getStartRes(), 0);
903     assertEquals(vpranges.getStartSeq(), 0);
904
905     // hide rows at end and check updated box position is correct
906     // no changes
907     int firstHidden = 500;
908     int lastHidden = 524;
909     hideSequences(firstHidden, lastHidden);
910
911     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
912     assertEquals(od.getBoxX(), 0);
913     assertEquals(od.getBoxY(), 0);
914     assertEquals(od.getBoxWidth(), boxWidth);
915     assertEquals(od.getBoxHeight(), boxHeight);
916
917     // click above hidden rows
918     int ypos = 40; // row 40
919     mouseClick(od, 0,
920             Math.round((float) ypos * od.getSequencesHeight() / alheight));
921     assertEquals(od.getBoxX(), 0);
922     assertEquals(od.getBoxY(),
923             Math.round((float) ypos * od.getSequencesHeight() / alheight));
924     assertEquals(od.getBoxWidth(), boxWidth);
925     assertEquals(od.getBoxHeight(), boxHeight);
926
927     // click above hidden rows so box overlaps
928     // boxY moved upwards, boxHeight remains same
929     ypos = 497; // row 497
930     mouseClick(od, 0,
931             Math.round((float) ypos * od.getSequencesHeight() / alheight));
932     assertEquals(od.getBoxX(), 0);
933     assertEquals(
934             od.getBoxY(),
935             Math.round((float) (firstHidden - viewHeight)
936                     * od.getSequencesHeight() / alheight));
937     assertEquals(od.getBoxWidth(), boxWidth);
938     assertEquals(od.getBoxHeight(), boxHeight);
939
940     // click within hidden rows
941     ypos = 505;
942     mouseClick(od, 0,
943             Math.round((float) ypos * od.getSequencesHeight() / alheight));
944     assertEquals(od.getBoxX(), 0);
945     assertEquals(
946             od.getBoxY(),
947             Math.round((firstHidden - viewHeight) * od.getSequencesHeight()
948                     / alheight));
949     assertEquals(od.getBoxWidth(), boxWidth);
950     assertEquals(od.getBoxHeight(), boxHeight);
951   }
952
953   /*
954    * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
955    */
956   private void moveViewportH(int startRes)
957   {
958     vpranges.setViewportStartAndWidth(startRes, viewWidth);
959     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
960   }
961
962   /*
963    * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
964    */
965   private void moveViewportV(int startSeq)
966   {
967     vpranges.setViewportStartAndHeight(startSeq, viewHeight);
968     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
969   }
970
971   /*
972    * Move viewport horizontally and vertically.
973    */
974   private void moveViewport(int startRes, int startSeq)
975   {
976     vpranges.setViewportStartAndWidth(startRes, viewWidth);
977     vpranges.setViewportStartAndHeight(startSeq, viewHeight);
978     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
979   }
980
981   /*
982    * Mouse click as position x,y in overview window
983    */
984   private void mouseClick(OverviewDimensions od, int x, int y)
985   {
986     od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols);
987
988     // updates require an OverviewPanel to exist which it doesn't here
989     // so call setBoxPosition() as it would be called by the AlignmentPanel
990     // normally
991     od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
992   }
993   
994   /*
995    * Test that the box is positioned with the top left corner at xpos, ypos
996    * and with the original width and height
997    */
998   private void testBoxIsAtClickPoint(int xpos, int ypos)
999   {
1000     mouseClick(od, xpos, ypos);
1001     assertEquals(od.getBoxX(), xpos);
1002     assertEquals(od.getBoxY(), ypos);
1003     assertEquals(od.getBoxWidth(), boxWidth);
1004     assertEquals(od.getBoxHeight(), boxHeight);
1005
1006   }
1007
1008   /*
1009    * Hide sequences between start and end
1010    */
1011   private void hideSequences(int start, int end)
1012   {
1013     SequenceI[] allseqs = al.getSequencesArray();
1014     SequenceGroup theseSeqs = new SequenceGroup();
1015     
1016     for (int i = start; i <= end; i++)
1017     {
1018       theseSeqs.addSequence(allseqs[i], false);
1019       al.getHiddenSequences().hideSequence(allseqs[i]);
1020     }
1021
1022     hiddenRepSequences.put(allseqs[start], theseSeqs);
1023   }
1024 }