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