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