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