Clover icon

Coverage Report

  1. Project Clover database Wed Dec 3 2025 16:47:11 GMT
  2. Package jalview.gui

File AlignmentPanelTest.java

 

Code metrics

12
159
13
1
470
285
20
0.13
12.23
13
1.54

Classes

Class Line # Actions
AlignmentPanelTest 55 159 20
0.5978260659.8%
 

Contributing tests

This file is covered by 11 tests. .

Source view

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