JAL-3562 wait until no more events on the queue as well
[jalview.git] / test / jalview / gui / AlignmentPanelTest.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.gui;
22
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertNotEquals;
25
26 import jalview.api.AlignViewportI;
27 import jalview.bin.Cache;
28 import jalview.bin.Jalview;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.SequenceI;
31 import jalview.io.DataSourceType;
32 import jalview.io.FileLoader;
33 import jalview.viewmodel.ViewportRanges;
34
35 import java.awt.Dimension;
36 import java.awt.Font;
37 import java.awt.FontMetrics;
38 import java.awt.Toolkit;
39
40 import org.testng.annotations.BeforeMethod;
41 import org.testng.annotations.Test;
42
43 public class AlignmentPanelTest
44 {
45   AlignFrame af;
46
47   @BeforeMethod(alwaysRun = true)
48   public void setUp()
49   {
50     Jalview.main(new String[] { "-nonews", "-props",
51         "test/jalview/testProps.jvprops" });
52
53     Cache.applicationProperties.setProperty("SHOW_IDENTITY",
54             Boolean.TRUE.toString());
55     af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
56             DataSourceType.FILE);
57
58     /*
59      * wait for Consensus thread to complete
60      */
61     synchronized (this)
62     {
63       while (af.getViewport().isCalcInProgress()
64               || Toolkit.getDefaultToolkit().getSystemEventQueue()
65                       .peekEvent() != null)
66       {
67         try
68         {
69           wait(50);
70         } catch (InterruptedException e)
71         {
72         }
73       }
74     }
75   }
76
77   /**
78    * Test side effect that end residue is set correctly by setScrollValues, with
79    * or without hidden columns
80    */
81   @Test(groups = "Functional")
82   public void testSetScrollValues()
83   {
84     ViewportRanges ranges = af.getViewport().getRanges();
85     af.alignPanel.setScrollValues(0, 0);
86
87     int oldres = ranges.getEndRes();
88     af.alignPanel.setScrollValues(-1, 5);
89
90     // setting -ve x value does not change residue
91     assertEquals(ranges.getEndRes(), oldres);
92
93     af.alignPanel.setScrollValues(0, 5);
94
95     // setting 0 as x value does not change residue
96     assertEquals(ranges.getEndRes(), oldres);
97
98     af.alignPanel.setScrollValues(5, 5);
99     // setting x value to 5 extends endRes by 5 residues
100     assertEquals(ranges.getEndRes(), oldres + 5);
101
102     // scroll to position after hidden columns sets endres to oldres (width) +
103     // position
104     int scrollpos = 60;
105     af.getViewport().hideColumns(30, 50);
106     af.alignPanel.setScrollValues(scrollpos, 5);
107     assertEquals(ranges.getEndRes(), oldres + scrollpos);
108
109     // scroll to position within hidden columns, still sets endres to oldres +
110     // position
111     // not sure if this is actually correct behaviour but this is what Jalview
112     // currently does
113     scrollpos = 40;
114     af.getViewport().showAllHiddenColumns();
115     af.getViewport().hideColumns(30, 50);
116     af.alignPanel.setScrollValues(scrollpos, 5);
117     assertEquals(ranges.getEndRes(), oldres + scrollpos);
118
119     // scroll to position within <width> distance of the end of the alignment
120     // endRes should be set to width of alignment - 1
121     scrollpos = 130;
122     af.getViewport().showAllHiddenColumns();
123     af.alignPanel.setScrollValues(scrollpos, 5);
124     assertEquals(ranges.getEndRes(), af.getViewport()
125             .getAlignment().getWidth() - 1);
126
127     // now hide some columns, and scroll to position within <width>
128     // distance of the end of the alignment
129     // endRes should be set to width of alignment - 1 - the number of hidden
130     // columns
131     af.getViewport().hideColumns(30, 50);
132     af.alignPanel.setScrollValues(scrollpos, 5);
133     assertEquals(ranges.getEndRes(), af.getViewport()
134             .getAlignment().getWidth() - 1 - 21); // 21 is the number of hidden
135                                                   // columns
136   }
137
138   /**
139    * Test that update layout reverts to original (unwrapped) values for endRes
140    * when switching from wrapped back to unwrapped mode (JAL-2739)
141    */
142   @Test(groups = "Functional")
143   public void testUpdateLayout_endRes()
144   {
145     // get details of original alignment dimensions
146     ViewportRanges ranges = af.getViewport().getRanges();
147     int endres = ranges.getEndRes();
148
149     // wrap
150     af.alignPanel.getAlignViewport().setWrapAlignment(true);
151     af.alignPanel.updateLayout();
152
153     // endRes has changed
154     assertNotEquals(ranges.getEndRes(), endres);
155
156     // unwrap
157     af.alignPanel.getAlignViewport().setWrapAlignment(false);
158     af.alignPanel.updateLayout();
159
160     // endRes back to original value
161     assertEquals(ranges.getEndRes(), endres);
162   }
163
164   /**
165    * Test the variant of calculateIdWidth that only recomputes the width if it is
166    * not already saved in the viewport (initial value is -1)
167    */
168   @Test(groups = "Functional")
169   public void testCalculateIdWidth_noArgs()
170   {
171     AlignViewportI av = af.alignPanel.getAlignViewport();
172     av.setShowJVSuffix(true);
173     av.setFont(new Font("Courier", Font.PLAIN, 15), true);
174
175     av.setIdWidth(0);
176     Dimension d = af.alignPanel.calculateIdWidth();
177     assertEquals(d.width, 0);
178     assertEquals(d.height, 0);
179
180     av.setIdWidth(99);
181     d = af.alignPanel.calculateIdWidth();
182     assertEquals(d.width, 99);
183     assertEquals(d.height, 0);
184
185     /*
186      * note 4 pixels padding are added to the longest sequence name width
187      */
188     av.setIdWidth(-1); // force recalculation
189     d = af.alignPanel.calculateIdWidth();
190     assertEquals(d.width, 166); // 4 + pixel width of "Q93Z60_ARATH/1-118"
191     assertEquals(d.height, 12);
192     assertEquals(d.width, av.getIdWidth());
193   }
194
195   /**
196    * Test the variant of calculateIdWidth that computes the longest of any
197    * sequence name or annotation label width
198    */
199   @Test(groups = "Functional")
200   public void testCalculateIdWidth_withMaxWidth()
201   {
202     AlignViewportI av = af.alignPanel.getAlignViewport();
203     av.setShowJVSuffix(true);
204     av.setFont(new Font("Courier", Font.PLAIN, 15), true);
205     av.setShowAnnotation(false);
206     av.setIdWidth(18);
207
208     /*
209      * note 4 pixels 'padding' are added to the longest seq name/annotation label
210      */
211     Dimension d = af.alignPanel.calculateIdWidth(2000);
212     assertEquals(d.width, 166); // 4 + pixel width of "Q93Z60_ARATH/1-118"
213     assertEquals(d.height, 12); // fixed value (not used?)
214     assertEquals(av.getIdWidth(), 18); // not changed by this method
215
216     /*
217      * make the longest sequence name longer
218      */
219     SequenceI seq = af.viewport.getAlignment()
220             .findSequenceMatch("Q93Z60_ARATH")[0];
221     seq.setName(seq.getName() + "MMMMM");
222     d = af.alignPanel.calculateIdWidth(2000);
223     assertEquals(d.width, 211); // 4 + pixel width of "Q93Z60_ARATHMMMMM/1-118"
224     assertEquals(d.height, 12);
225     assertEquals(av.getIdWidth(), 18); // unchanged
226
227     /*
228      * make the longest annotation name even longer
229      * note this is checked even if annotations are not shown
230      */
231     AlignmentAnnotation aa = av.getAlignment().getAlignmentAnnotation()[0];
232     aa.label = "THIS IS A VERY LONG LABEL INDEED";
233     FontMetrics fmfor = af.alignPanel
234             .getFontMetrics(af.alignPanel.getAlabels().getFont());
235     // Assumption ID_WIDTH_PADDING == 4
236     int expwidth = 4 + fmfor.stringWidth(aa.label);
237     d = af.alignPanel.calculateIdWidth(2000);
238     assertEquals(d.width, expwidth); // 228 == ID_WIDTH_PADDING + pixel width of "THIS IS A VERY LONG LABEL INDEED"
239     assertEquals(d.height, 12);
240
241     /*
242      * override with maxwidth
243      * note the 4 pixels padding is added to this value
244      */
245     d = af.alignPanel.calculateIdWidth(213);
246     assertEquals(d.width, 217);
247     assertEquals(d.height, 12);
248   }
249
250   @Test(groups = { "Functional", "Not-bamboo" })
251   public void testGetVisibleWidth()
252   {
253     /*
254      * width for onscreen rendering is IDPanel width
255      */
256     int w = af.alignPanel.getVisibleIdWidth(true);
257     assertEquals(w, af.alignPanel.getIdPanel().getWidth());
258     assertEquals(w, 115);
259
260     /*
261      * width for offscreen rendering is the same
262      * if no fixed id width is specified in preferences
263      */
264     Cache.setProperty("FIGURE_AUTOIDWIDTH", Boolean.FALSE.toString());
265     Cache.removeProperty("FIGURE_FIXEDIDWIDTH");
266     assertEquals(w, af.alignPanel.getVisibleIdWidth(false));
267
268     /*
269      * preference for fixed id width - note 4 pixels padding is added
270      */
271     Cache.setProperty("FIGURE_FIXEDIDWIDTH", "120");
272     assertEquals(124, af.alignPanel.getVisibleIdWidth(false));
273
274     /*
275      * preference for auto id width overrides fixed width
276      */
277     Cache.setProperty("FIGURE_AUTOIDWIDTH", Boolean.TRUE.toString());
278     assertEquals(115, af.alignPanel.getVisibleIdWidth(false));
279   }
280 }