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