JAL-2388 Unit tests for columns, take 1
[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.SequenceI;
30 import jalview.gui.AlignFrame;
31 import jalview.gui.AlignViewport;
32 import jalview.io.DataSourceType;
33 import jalview.io.FileLoader;
34
35 import org.testng.annotations.AfterClass;
36 import org.testng.annotations.BeforeMethod;
37 import org.testng.annotations.Test;
38
39 public class OverviewDimensionsTest {
40
41   boolean showConservationSetting;
42
43   SequenceI seq1 = new Sequence(
44           "Seq1",
45           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
46
47   SequenceI seq2 = new Sequence(
48           "Seq2",
49           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
50
51   SequenceI seq3 = new Sequence(
52           "Seq3",
53           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
54
55   SequenceI seq4 = new Sequence(
56           "Seq4",
57           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
58
59   SequenceI seq5 = new Sequence(
60           "Seq5",
61           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
62
63   SequenceI seq6 = new Sequence(
64           "Seq6",
65           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
66
67   SequenceI seq7 = new Sequence(
68           "Seq7",
69           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
70
71   SequenceI seq8 = new Sequence(
72           "Seq8",
73           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
74
75   SequenceI seq9 = new Sequence(
76           "Seq9",
77           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
78
79   SequenceI seq10 = new Sequence(
80           "Seq10",
81           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
82
83   SequenceI seq11 = new Sequence(
84           "Seq11",
85           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
86
87   SequenceI seq12 = new Sequence(
88           "Seq12",
89           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
90
91   SequenceI seq13 = new Sequence(
92           "Seq13",
93           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
94
95   SequenceI seq14 = new Sequence(
96           "Seq14",
97           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
98
99   SequenceI seq15 = new Sequence(
100           "Seq15",
101           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
102
103   SequenceI seq16 = new Sequence(
104           "Seq16",
105           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
106
107   SequenceI seq17 = new Sequence(
108           "Seq17",
109           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
110
111   SequenceI seq18 = new Sequence(
112           "Seq18",
113           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
114
115   SequenceI seq19 = new Sequence(
116           "Seq19",
117           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
118
119   SequenceI seq20 = new Sequence(
120           "Seq20",
121           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
122
123   SequenceI seq21 = new Sequence(
124           "Seq21",
125           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
126
127   SequenceI seq22 = new Sequence(
128           "Seq22",
129           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC"
130                   + "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC"
131                   + "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC"
132                   + "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC"
133                   + "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
134
135   SequenceI seq23 = new Sequence(
136           "Seq23",
137           "ABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBACABCABCABCABCABCABCABCABCBACBACBACBAC");
138
139   AlignFrame af;
140   AlignViewport av;
141   OverviewDimensions od;
142
143   float scalew;
144   float scaleh;
145   int boxWidth;
146   int boxHeight;
147
148   @BeforeMethod(alwaysRun = true)
149   public void setUp()
150   {
151     Jalview.main(new String[] { "-nonews", "-props",
152         "test/jalview/testProps.jvprops" });
153
154     Cache.applicationProperties.setProperty("SHOW_IDENTITY",
155             Boolean.TRUE.toString());
156     af = new FileLoader().LoadFileWaitTillLoaded(
157             "examples/testdata/bigal.fa",
158             DataSourceType.FILE);
159
160     /*
161      * wait for Consensus thread to complete
162      */
163     synchronized (this)
164     {
165       while (af.getViewport().getConsensusSeq() == null)
166       {
167         try
168         {
169           wait(50);
170         } catch (InterruptedException e)
171         {
172         }
173       }
174     }
175     // get cached setting for showConservation
176     // reset it in AfterClass!
177     showConservationSetting = Cache.getDefault("SHOW_CONSERVATION", true);
178     
179     av = af.getViewport();
180     od = new OverviewDimensions(av);
181
182     // Initial box sizing - default path through code
183     od.setBoxPosition();
184     scalew = (float) od.getWidth()
185             / (av.getAlignment().getWidth() * av.getCharWidth());
186     scaleh = (float) od.getSequencesHeight()
187             / (av.getAlignment().getHeight() * av.getCharHeight());
188     boxWidth = (int) ((av.getEndRes() - av.getStartRes() + 1)
189             * av.getCharWidth() * scalew);
190     boxHeight = (int) ((av.getEndSeq() - av.getStartSeq())
191             * av.getCharHeight() * scaleh);
192   }
193
194
195   @AfterClass(alwaysRun = true)
196   public void tearDown()
197   {
198     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
199             Boolean.toString(showConservationSetting));
200   }
201
202   /**
203    * Test that the OverviewDimensions constructor sets width and height
204    * correctly
205    */
206   @Test(groups = { "Functional" })
207   public void testConstructor()
208   {
209     SequenceI seqa = new Sequence("Seq1", "ABC");
210     SequenceI seqb = new Sequence("Seq2", "ABC");
211     SequenceI seqc = new Sequence("Seq3", "ABC");
212     SequenceI seqd = new Sequence("Seq4", "ABC");
213     SequenceI seqe = new Sequence("Seq5",
214             "ABCABCABCABCABCABCABCABCBACBACBACBAC");
215
216     int defaultGraphHeight = 20;
217     int maxWidth = 400;
218     int minWidth = 120;
219     int maxSeqHeight = 300;
220     int minSeqHeight = 40;
221
222     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
223             Boolean.toString(true));
224
225     // test for alignment with width > height
226     SequenceI[] seqs1 = new SequenceI[] { seqa, seqb };
227     Alignment al1 = new Alignment(seqs1);
228     al1.setDataset(null);
229     AlignViewport av1 = new AlignViewport(al1);
230
231     OverviewDimensions od = new OverviewDimensions(av1);
232     int scaledHeight = 266;
233     assertEquals(od.getGraphHeight(), defaultGraphHeight);
234     assertEquals(od.getSequencesHeight(), scaledHeight);
235     assertEquals(od.getWidth(), maxWidth);
236     assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight);
237
238     // test for alignment with width < height
239     SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd };
240     Alignment al2 = new Alignment(seqs2);
241     al2.setDataset(null);
242     AlignViewport av2 = new AlignViewport(al2);
243
244     od = new OverviewDimensions(av2);
245     int scaledWidth = 300;
246     assertEquals(od.getGraphHeight(), defaultGraphHeight);
247     assertEquals(od.getSequencesHeight(), maxSeqHeight);
248     assertEquals(od.getWidth(), scaledWidth);
249     assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight);
250
251     // test for alignment with width > height and sequence height scaled below
252     // min value
253     SequenceI[] seqs3 = new SequenceI[] { seqe };
254     Alignment al3 = new Alignment(seqs3);
255     al3.setDataset(null);
256     AlignViewport av3 = new AlignViewport(al3);
257
258     od = new OverviewDimensions(av3);
259     assertEquals(od.getGraphHeight(), defaultGraphHeight);
260     assertEquals(od.getSequencesHeight(), minSeqHeight);
261     assertEquals(od.getWidth(), maxWidth);
262     assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight);
263
264     // test for alignment with width < height and width scaled below min value
265     SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa,
266         seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd };
267     Alignment al4 = new Alignment(seqs4);
268     al4.setDataset(null);
269     AlignViewport av4 = new AlignViewport(al4);
270
271     od = new OverviewDimensions(av4);
272     assertEquals(od.getGraphHeight(), defaultGraphHeight);
273     assertEquals(od.getSequencesHeight(), maxSeqHeight);
274     assertEquals(od.getWidth(), minWidth);
275     assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight);
276
277     // test for alignment where no conservation annotation is shown
278     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
279             Boolean.toString(false));
280
281     Alignment al5 = new Alignment(seqs4);
282     al5.setDataset(null);
283     AlignViewport av5 = new AlignViewport(al5);
284
285     od = new OverviewDimensions(av5);
286     assertEquals(od.getGraphHeight(), 0);
287     assertEquals(od.getSequencesHeight(), maxSeqHeight);
288     assertEquals(od.getWidth(), minWidth);
289     assertEquals(od.getHeight(), maxSeqHeight);
290   }
291
292   /**
293    * Test that validation after mouse adjustments to boxX and boxY sets box
294    * dimensions and scroll values correctly, when there are no hidden rows or
295    * columns.
296    * 
297    * The current implementation uses multiple transformations between coordinate
298    * systems which often involve casting to int, which causes values to be
299    * truncated. As a result we can lose accuracy. The tests below use
300    * approximate test values where appropriate.
301    */
302   @Test(groups = { "Functional" })
303   public void testSetBoxFromMouseClick()
304   {
305     od.checkValid();
306     assertEquals(od.getBoxX(), 0);
307     assertEquals(od.getBoxY(), 0);
308     assertEquals(od.getBoxWidth(), boxWidth);
309     assertEquals(od.getScrollCol(), 0);
310     assertEquals(od.getScrollRow(), 0);
311
312     // negative boxX value reset to 0
313     mouseClick(od, -5, 10);
314     assertEquals(od.getBoxX(), 0);
315     assertEquals(od.getBoxWidth(), boxWidth);
316     assertEquals(od.getBoxHeight(), boxHeight);
317     assertEquals(od.getScrollRow(),
318             (int) (10 / scaleh / av.getCharHeight()));
319     assertEquals(od.getScrollCol(), 0);
320
321     // negative boxY value reset to 0
322     mouseClick(od, 6, -2);
323     assertEquals(od.getBoxY(), 0);
324     assertEquals(od.getBoxWidth(), boxWidth);
325     assertEquals(od.getBoxHeight(), boxHeight);
326     assertEquals(od.getScrollCol(), (int) (6 / scalew / av.getCharWidth()));
327     assertEquals(od.getScrollRow(), 0);
328
329     // overly large boxX value reset to width-boxWidth
330     mouseClick(od, 100, 6);
331     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth(), 1.5);
332     assertEquals(od.getBoxY(), 6, 1.5);
333     assertEquals(od.getBoxWidth(), boxWidth);
334     assertEquals(od.getBoxHeight(), boxHeight);
335     assertEquals(od.getScrollCol(),
336             (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
337     assertEquals(od.getScrollRow(),
338             (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
339
340     // overly large boxY value reset to sequenceHeight - boxHeight
341     mouseClick(od, 10, 520);
342     assertEquals(od.getBoxX(), 10, 1.5);
343     assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight(),
344             1.5);
345     assertEquals(od.getBoxWidth(), boxWidth);
346     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
347     assertEquals(od.getScrollCol(),
348             (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
349     assertEquals(od.getScrollRow(),
350             (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
351
352     // click past end of alignment, as above
353     mouseClick(od, 3000, 5);
354     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth(), 1.5);
355     assertEquals(od.getBoxWidth(), boxWidth);
356     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
357     assertEquals(od.getScrollCol(),
358             (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
359     assertEquals(od.getScrollRow(),
360             (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
361
362     // move viewport so startRes non-zero and then mouseclick
363     moveViewportH(av, od, 50);
364
365     // click at viewport position
366     int oldboxx = od.getBoxX();
367     int oldboxy = od.getBoxY();
368     mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2);
369     assertEquals(od.getBoxX(), oldboxx + 5, 1.5);
370     assertEquals(od.getBoxWidth(), boxWidth);
371     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
372     assertEquals(od.getScrollCol(),
373             (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
374     assertEquals(od.getBoxY(), oldboxy + 2, 1.5);
375     assertEquals(od.getScrollRow(),
376             (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
377
378     // click at top corner
379     mouseClick(od, 0, 0);
380     assertEquals(od.getBoxX(), 0);
381     assertEquals(od.getScrollCol(), 0);
382     assertEquals(od.getBoxY(), 0);
383     assertEquals(od.getScrollRow(), 0);
384     assertEquals(od.getBoxWidth(), boxWidth);
385     assertEquals(od.getBoxHeight(), boxHeight, 1.5);
386   }
387
388   /**
389    * Test setting of the box position, when there are hidden cols at the start
390    * of the alignment
391    */
392   @Test(groups = { "Functional" })
393   public void testFromMouseWithHiddenColsAtStart()
394   {
395     od.checkValid();
396     assertEquals(od.getBoxX(), 0);
397     assertEquals(od.getBoxY(), 0);
398     assertEquals(od.getBoxWidth(), boxWidth);
399     assertEquals(od.getScrollCol(), 0);
400     assertEquals(od.getScrollRow(), 0);
401
402     // hide cols at start and check updated box position is correct
403     // changes boxX but not boxwidth
404     int lastHiddenCol = 30;
405     av.hideColumns(0, lastHiddenCol);
406     od.setBoxPosition();
407     assertEquals(od.getBoxX(),
408             (int) ((lastHiddenCol + 1) * scalew * av.getCharWidth()));
409     assertEquals(od.getBoxWidth(), boxWidth);
410     assertEquals(od.getBoxHeight(), boxHeight);
411
412     // try to click in hidden cols, check box does not move
413     // this test currently fails as the overview box does not behave like this!
414     /*    int xpos = 10;
415         mouseClick(od, xpos, 0);
416         assertEquals(od.getBoxX(),
417                 (int) ((lastHiddenCol + 1) * scalew * av.getCharWidth()));
418         assertEquals(od.getBoxY(), 0);
419         assertEquals(od.getBoxWidth(), boxWidth);
420         assertEquals(od.getBoxHeight(), boxHeight);
421         assertEquals(od.getScrollRow(), 0);
422         assertEquals(od.getScrollCol(),
423                 (int) (xpos / scalew / av.getCharWidth()));
424     */
425     // click to right of hidden columns, box moves to click point
426     testBoxIsAtClickPoint(40, 0);
427     assertEquals(od.getScrollRow(), 0);
428     assertEquals(od.getScrollCol(),
429  (int) (40 / scalew / av.getCharWidth())
430             - lastHiddenCol, 1.5);
431
432     // click to right of hidden columns such that box runs over right hand side
433     // of alignment
434     // box position is adjusted away from the edge
435     // overly large boxX value reset to width-boxWidth
436     int xpos = 100;
437     mouseClick(od, xpos, 5);
438     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth(), 1.5);
439     assertEquals(od.getBoxY(), 5, 1.5);
440     assertEquals(od.getBoxWidth(), boxWidth);
441     assertEquals(od.getBoxHeight(), boxHeight);
442     assertEquals(od.getScrollCol(),
443             (int) (od.getBoxX() / scalew / av.getCharWidth())
444                     - lastHiddenCol, 1.5);
445     assertEquals(od.getScrollRow(),
446             (int) (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
447
448   }
449
450   /**
451    * Test setting of the box position, when there are hidden cols in the middle
452    * of the alignment
453    */
454   @Test(groups = { "Functional" })
455   public void testFromMouseWithHiddenColsInMiddle()
456   {
457     od.checkValid();
458     assertEquals(od.getBoxX(), 0);
459     assertEquals(od.getBoxY(), 0);
460     assertEquals(od.getBoxWidth(), boxWidth);
461     assertEquals(od.getScrollCol(), 0);
462     assertEquals(od.getScrollRow(), 0);
463     
464     // hide columns 60-68, no change to box position or dimensions
465     int firstHidden = 60;
466     int lastHidden = 68;
467     av.hideColumns(firstHidden, lastHidden);
468     od.setBoxPosition();
469     assertEquals(od.getBoxX(), 0);
470     assertEquals(od.getBoxY(), 0);
471     assertEquals(od.getBoxWidth(), boxWidth);
472     assertEquals(od.getScrollCol(), 0);
473     assertEquals(od.getScrollRow(), 0);
474     
475     // move box so that it overlaps with hidden cols on one side
476     // box width changes, boxX and scrollCol as for unhidden case
477     int xpos = 50 - boxWidth; // 50 is position in overview halfway between cols
478                               // 60 and 70
479     mouseClick(od, xpos, 0);
480     assertEquals(od.getBoxX(), xpos, 1.5);
481     assertEquals(od.getBoxY(), 0);
482     assertEquals(od.getBoxWidth(), boxWidth
483             + (lastHidden - firstHidden + 1) * scalew * av.getCharWidth(),
484             1.5);
485     assertEquals(od.getBoxHeight(), boxHeight);
486     assertEquals(od.getScrollCol(), (int) (xpos / scalew / av.getCharWidth()), 1.5);
487     assertEquals(od.getScrollRow(), 0);
488
489     // move box so that it completely covers hidden cols
490     // box width changes, boxX and scrollCol as for hidden case
491     xpos = 30;
492     mouseClick(od, xpos, 0);
493     assertEquals(od.getBoxX(), xpos, 1.5);
494     assertEquals(od.getBoxY(), 0);
495     assertEquals(od.getBoxWidth(), boxWidth
496             + (lastHidden - firstHidden + 1) * scalew * av.getCharWidth(),
497             1.5);
498     assertEquals(od.getBoxHeight(), boxHeight);
499     assertEquals(od.getScrollCol(),
500             (int) (xpos / scalew / av.getCharWidth()), 1.5);
501     assertEquals(od.getScrollRow(), 0);
502
503     // move box so boxX is in hidden cols, box overhangs at right
504     // box width back to normal, boxX and scrollCol move to right of hidden area
505     // TODO currently this test fails in the Jalview GUI, there is a gap between
506     // the rhs of the hidden area and the box
507     /*    xpos = 50;
508         mouseClick(od, xpos, 0);
509         assertEquals(od.getBoxX(),
510                 (lastHidden + 1) * scalew * av.getCharWidth(), 1.5);
511         assertEquals(od.getBoxY(), 0);
512         assertEquals(od.getBoxWidth(), boxWidth, 1.5);
513         assertEquals(od.getBoxHeight(), boxHeight);
514         assertEquals(od.getScrollCol(),
515                 (int) (xpos / scalew / av.getCharWidth()), 1.5);
516         assertEquals(od.getScrollRow(), 0);*/
517
518     // move box so boxX is to right of hidden cols, but does not go beyond full
519     // width of alignment
520     // box width, boxX and scrollCol all as for non-hidden case
521     // TODO currently this test fails in the Jalview GUI because boxX is
522     // calculated
523     // based on the current boxWidth, which includes hidden columns, thereby
524     // pushing
525     // the box off the end of the alignment. So boxX is adjusted backwards
526     // unnecessarily.
527     /*   xpos = 72;
528        testBoxIsAtClickPoint(xpos, 0);
529        assertEquals(od.getScrollRow(), 0);
530        assertEquals(od.getScrollCol(),
531                (int) (xpos / scalew / av.getCharWidth())
532                - lastHidden, 1.5);*/
533     
534     // move box so it goes beyond full width of alignment
535     // boxX, scrollCol adjusted back, box width normal
536     xpos = 3000;
537     mouseClick(od, xpos, 5);
538     assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth(), 1.5);
539     assertEquals(od.getBoxY(), 5, 1.5);
540     assertEquals(od.getBoxWidth(), boxWidth);
541     assertEquals(od.getBoxHeight(), boxHeight);
542     assertEquals(od.getScrollCol(),
543             (od.getBoxX() / scalew / av.getCharWidth())
544                     - (lastHidden - firstHidden + 1),
545             1.5);
546     assertEquals(od.getScrollRow(),
547             (int) (od.getBoxY() / scaleh / av.getCharHeight()), 1.5);
548
549   }
550
551   /**
552    * Test setting of the box position, when there are hidden cols at the end of
553    * the alignment
554    */
555   @Test(groups = { "Functional" })
556   public void testFromMouseWithHiddenColsAtEnd()
557   {
558     od.checkValid();
559     assertEquals(od.getBoxX(), 0);
560     assertEquals(od.getBoxY(), 0);
561     assertEquals(od.getBoxWidth(), boxWidth);
562     assertEquals(od.getScrollCol(), 0);
563     assertEquals(od.getScrollRow(), 0);
564
565     // hide columns 140-157, no change to box position or dimensions
566     int firstHidden = 140;
567     int lastHidden = 157;
568     av.hideColumns(firstHidden, lastHidden);
569     od.setBoxPosition();
570     assertEquals(od.getBoxX(), 0);
571     assertEquals(od.getBoxY(), 0);
572     assertEquals(od.getBoxWidth(), boxWidth);
573     assertEquals(od.getScrollCol(), 0);
574     assertEquals(od.getScrollRow(), 0);
575
576     // click to left of hidden cols, without overlapping
577     // boxX, scrollCol and width as normal
578     int xpos = 5;
579     testBoxIsAtClickPoint(xpos, 0);
580     assertEquals(od.getScrollRow(), 0);
581     assertEquals(od.getScrollCol(),
582             (int) (xpos / scalew / av.getCharWidth()), 1.5);
583
584     // click to left of hidden cols, with overlap
585     // boxX and scrollCol adjusted for hidden cols, width normal
586     // TODO this fails because setBoxPosition screws up the hidden cols calc
587     // only works in GUI because of AlignmentPanel::setScrollValues
588     /*xpos = 115 - boxWidth;
589     mouseClick(od, xpos, 0);
590     assertEquals(
591             od.getBoxX(),
592             (int) ((firstHidden - 1) * scalew * av.getCharWidth())
593                     - od.getBoxWidth(), 1.5);
594     assertEquals(od.getBoxY(), 0);
595     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
596     assertEquals(od.getBoxHeight(), boxHeight);
597     assertEquals(od.getScrollCol(),
598             (int) (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
599     assertEquals(od.getScrollRow(), 0);*/
600
601     // click in hidden cols
602     // boxX and scrollCol adjusted for hidden cols, width normal
603     // TODO breaks as above test
604     /*xpos = 115;
605     assertEquals(
606             od.getBoxX(),
607             (int) ((firstHidden - 1) * scalew * av.getCharWidth())
608                     - od.getBoxWidth(), 1.5);
609     assertEquals(od.getBoxY(), 0);
610     assertEquals(od.getBoxWidth(), boxWidth, 1.5);
611     assertEquals(od.getBoxHeight(), boxHeight);
612     assertEquals(od.getScrollCol(),
613             (int) (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
614     assertEquals(od.getScrollRow(), 0);*/
615
616     // click off end of alignment
617     // boxX and scrollCol adjusted for hidden cols, width normal
618     // TODO breaks as above test
619     /*    xpos = 3000;
620         assertEquals(
621                 od.getBoxX(),
622                 (int) ((firstHidden - 1) * scalew * av.getCharWidth())
623                         - od.getBoxWidth(), 1.5);
624         assertEquals(od.getBoxY(), 0);
625         assertEquals(od.getBoxWidth(), boxWidth, 1.5);
626         assertEquals(od.getBoxHeight(), boxHeight);
627         assertEquals(od.getScrollCol(),
628                 (int) (od.getBoxX() / scalew / av.getCharWidth()), 1.5);
629         assertEquals(od.getScrollRow(), 0);*/
630   }
631
632   /**
633    * Test that the box position is set correctly when set from the viewport,
634    * with no hidden rows or columns
635    */
636   @Test(groups = { "Functional" })
637   public void testSetBoxFromViewport()
638   {
639     // move viewport to start of alignment
640     moveViewport(av, od, 0, 0);
641     assertEquals(od.getBoxX(), 0);
642     assertEquals(od.getBoxY(), 0);
643     assertEquals(od.getBoxWidth(), boxWidth);
644     assertEquals(od.getBoxHeight(), boxHeight);
645
646     // move viewport to right
647     moveViewportH(av, od, 70);
648     assertEquals(od.getBoxX(), (int) (70 * scalew * av.getCharWidth()));
649     assertEquals(od.getBoxY(), 0);
650     assertEquals(od.getBoxWidth(), boxWidth);
651     assertEquals(od.getBoxHeight(), boxHeight);
652
653     // move viewport down
654     moveViewportV(av, od, 100);
655     assertEquals(od.getBoxX(), (int) (70 * scalew * av.getCharWidth()));
656     assertEquals(od.getBoxY(), (int) (100 * scaleh * av.getCharHeight()));
657     assertEquals(od.getBoxWidth(), boxWidth);
658     assertEquals(od.getBoxHeight(), boxHeight);
659
660     // move viewport to bottom right
661     moveViewport(av, od, 98, 508);
662     assertEquals(od.getBoxX(), (int) (98 * scalew * av.getCharWidth()));
663     assertEquals(od.getBoxY(), (int) (508 * scaleh * av.getCharHeight()));
664     assertEquals(od.getBoxWidth(), boxWidth);
665     assertEquals(od.getBoxHeight(), boxHeight);
666   }
667
668   /**
669    * Test that the box position is set correctly when there are hidden columns
670    * at the start
671    */
672   @Test(groups = { "Functional" })
673   public void testSetBoxFromViewportHiddenColsAtStart()
674   {
675     int firstHidden = 0;
676     int lastHidden = 20;
677     av.hideColumns(firstHidden, lastHidden);
678
679     // move viewport to start of alignment
680     moveViewport(av, od, 0, 0);
681     assertEquals(od.getBoxX(),
682             (int) ((lastHidden + 1) * scalew * av.getCharWidth()));
683     assertEquals(od.getBoxY(), 0);
684     assertEquals(od.getBoxWidth(), boxWidth);
685     assertEquals(od.getBoxHeight(), boxHeight);
686
687     // move viewport to end of alignment - need to make startRes by removing
688     // hidden cols because of how viewport/overview are implemented
689     moveViewport(av, od, 98 - lastHidden - 1, 0);
690     assertEquals(od.getBoxX(), 98 * scalew * av.getCharWidth(), 1.5);
691     assertEquals(od.getBoxY(), 0);
692     assertEquals(od.getBoxWidth(), boxWidth);
693     assertEquals(od.getBoxHeight(), boxHeight);
694   }
695
696   /**
697    * Test that the box position is set correctly when there are hidden columns
698    * in the middle
699    */
700   @Test(groups = { "Functional" })
701   public void testSetBoxFromViewportHiddenColsInMiddle()
702   {
703     int firstHidden = 65;
704     int lastHidden = 75;
705     av.hideColumns(firstHidden, lastHidden);
706
707     // move viewport before hidden columns
708     moveViewport(av, od, 3, 0);
709     assertEquals(od.getBoxX(), (int) (3 * scalew * av.getCharWidth()));
710     assertEquals(od.getBoxY(), 0);
711     assertEquals(od.getBoxWidth(), boxWidth);
712     assertEquals(od.getBoxHeight(), boxHeight);
713
714     // move viewport to left of hidden columns with overlap
715     moveViewport(av, od, 10, 0);
716     assertEquals(od.getBoxX(), (int) (10 * scalew * av.getCharWidth()));
717     assertEquals(od.getBoxY(), 0);
718     assertEquals(
719             od.getBoxWidth(),
720             boxWidth
721                     + (int) ((lastHidden - firstHidden + 1) * scalew * av
722                             .getCharWidth()), 1.5);
723     assertEquals(od.getBoxHeight(), boxHeight);
724
725     // move viewport to straddle hidden columns
726     moveViewport(av, od, 60, 0);
727     assertEquals(od.getBoxX(), (int) (60 * scalew * av.getCharWidth()));
728     assertEquals(od.getBoxY(), 0);
729     assertEquals(
730             od.getBoxWidth(),
731             boxWidth
732                     + (int) ((lastHidden - firstHidden + 1) * scalew * av
733                             .getCharWidth()), 1.5);
734     assertEquals(od.getBoxHeight(), boxHeight);
735
736     // move viewport to right of hidden columns, no overlap
737     moveViewport(av, od, 80 - (lastHidden - firstHidden + 1), 0);
738     assertEquals(od.getBoxX(), (int) (80 * scalew * av.getCharWidth()), 1.5);
739     assertEquals(od.getBoxY(), 0);
740     assertEquals(od.getBoxWidth(), boxWidth);
741     assertEquals(od.getBoxHeight(), boxHeight);
742
743   }
744
745   /**
746    * Test that the box position is set correctly when there are hidden columns
747    * at the end
748    */
749   @Test(groups = { "Functional" })
750   public void testSetBoxFromViewportHiddenColsAtEnd()
751   {
752     int firstHidden = 145;
753     int lastHidden = 157;
754     av.hideColumns(firstHidden, lastHidden);
755
756     // move viewport before hidden columns
757     moveViewport(av, od, 3, 0);
758     assertEquals(od.getBoxX(), (int) (3 * scalew * av.getCharWidth()), 1.5);
759     assertEquals(od.getBoxY(), 0);
760     assertEquals(od.getBoxWidth(), boxWidth);
761     assertEquals(od.getBoxHeight(), boxHeight);
762
763     // move viewport to hidden columns
764     // TODO boxwidth includes hidden in overview panel (why?)
765     moveViewport(av, od, 98, 0);
766     assertEquals(od.getBoxX(), (int) (98 * scalew * av.getCharWidth()), 1.5);
767     assertEquals(od.getBoxY(), 0);
768     assertEquals(
769             od.getBoxWidth(),
770             boxWidth
771                     + (int) ((lastHidden - firstHidden + 1) * scalew * av
772                             .getCharWidth()), 1.5);
773     assertEquals(od.getBoxHeight(), boxHeight);
774   }
775
776   /*
777    * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
778    */
779   private void moveViewportH(AlignViewport av, OverviewDimensions od,
780           int startRes)
781   {
782     int width = av.getEndRes() - av.getStartRes();
783     av.setStartRes(startRes);
784     av.setEndRes(startRes + width);
785     od.setBoxPosition();
786   }
787
788   /*
789    * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
790    */
791   private void moveViewportV(AlignViewport av, OverviewDimensions od,
792           int startSeq)
793   {
794     int height = av.getEndSeq() - av.getStartSeq();
795     av.setStartSeq(startSeq);
796     av.setEndSeq(startSeq + height);
797     od.setBoxPosition();
798   }
799
800   /*
801    * Move viewport horizontally and vertically.
802    */
803   private void moveViewport(AlignViewport av, OverviewDimensions od,
804           int startRes, int startSeq)
805   {
806     int width = av.getEndRes() - av.getStartRes();
807     int height = av.getEndSeq() - av.getStartSeq();
808     av.setStartRes(startRes);
809     av.setEndRes(startRes + width);
810     av.setStartSeq(startSeq);
811     av.setEndSeq(startSeq + height);
812     od.setBoxPosition();
813   }
814
815   /*
816    * Mouse click as position x,y in overview window
817    */
818   private void mouseClick(OverviewDimensions od, int x, int y)
819   {
820     od.setBoxX(x);
821     od.setBoxY(y);
822     od.checkValid();
823     // updates require an OverviewPanel to exist which it doesn't here
824     // so call setBoxPosition() as it would be called by the AlignmentPanel
825     // normally
826     AlignViewport av = af.getViewport();
827     int width = av.getEndRes() - av.getStartRes();
828     int height = av.getEndSeq() - av.getStartSeq();
829     av.setStartRes(od.getScrollCol());
830     av.setEndRes(od.getScrollCol() + width);
831     av.setStartSeq(od.getScrollRow());
832     av.setEndSeq(od.getScrollRow() + height);
833     od.setBoxPosition();
834   }
835   
836   private void testBoxIsAtClickPoint(int xpos, int ypos)
837   {
838     mouseClick(od, xpos, ypos);
839     assertEquals(od.getBoxX(), xpos, 1.5);
840     assertEquals(od.getBoxY(), ypos, 1.5);
841     assertEquals(od.getBoxWidth(), boxWidth);
842     assertEquals(od.getBoxHeight(), boxHeight);
843
844   }
845 }