cf97711a971e16e584f8518eb769ce5aa95331d8
[jalview.git] / test / jalview / gui / AnnotationChooserTest.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.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertTrue;
26
27 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
28 import jalview.bin.Cache;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.Annotation;
32 import jalview.datamodel.SequenceGroup;
33 import jalview.datamodel.SequenceI;
34 import jalview.io.DataSourceType;
35 import jalview.io.FileFormat;
36 import jalview.io.FormatAdapter;
37 import jalview.util.MessageManager;
38
39 import java.awt.BorderLayout;
40 import java.awt.Checkbox;
41 import java.awt.Component;
42 import java.awt.Container;
43 import java.awt.FlowLayout;
44 import java.awt.event.ItemEvent;
45 import java.io.IOException;
46 import java.util.List;
47
48 import javax.swing.JButton;
49 import javax.swing.JPanel;
50
51 import org.testng.annotations.BeforeClass;
52 import org.testng.annotations.BeforeMethod;
53 import org.testng.annotations.Test;
54
55 /**
56  * Unit tests for AnnotationChooser
57  * 
58  * @author gmcarstairs
59  *
60  */
61 public class AnnotationChooserTest
62 {
63   /*
64    * number of automatically computed annotation rows
65    * (Conservation, Quality, Consensus, Occupancy)
66    */
67   private static final int AUTOCALCD = 4;
68
69   @BeforeClass(alwaysRun = true)
70   public void setUpJvOptionPane()
71   {
72     JvOptionPane.setInteractiveMode(false);
73     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
74   }
75
76   // 4 sequences x 13 positions
77   final static String TEST_DATA = ">FER_CAPAA Ferredoxin\n"
78           + "TIETHKEAELVG-\n"
79           + ">FER_CAPAN Ferredoxin, chloroplast precursor\n"
80           + "TIETHKEAELVG-\n"
81           + ">FER1_SOLLC Ferredoxin-1, chloroplast precursor\n"
82           + "TIETHKEEELTA-\n" + ">Q93XJ9_SOLTU Ferredoxin I precursor\n"
83           + "TIETHKEEELTA-\n";
84
85   AnnotationChooser testee;
86
87   AlignmentPanel parentPanel;
88
89   AlignFrame af;
90
91   @BeforeMethod(alwaysRun = true)
92   public void setUp() throws IOException
93   {
94     Cache.loadProperties("test/jalview/io/testProps.jvprops");
95     // pin down annotation sort order for test
96     Cache.applicationProperties.setProperty(Preferences.SORT_ANNOTATIONS,
97             SequenceAnnotationOrder.NONE.name());
98     final String TRUE = Boolean.TRUE.toString();
99     Cache.applicationProperties.setProperty(
100             Preferences.SHOW_AUTOCALC_ABOVE, TRUE);
101     Cache.applicationProperties.setProperty("SHOW_QUALITY", TRUE);
102     Cache.applicationProperties.setProperty("SHOW_CONSERVATION", TRUE);
103     Cache.applicationProperties.setProperty("SHOW_IDENTITY", TRUE);
104
105     AlignmentI al = new FormatAdapter().readFile(TEST_DATA,
106             DataSourceType.PASTE, FileFormat.Fasta);
107     af = new AlignFrame(al, 700, 500);
108     parentPanel = new AlignmentPanel(af, af.getViewport());
109     addAnnotations();
110   }
111
112   /**
113    * Add 4 annotations, 3 of them sequence-specific.
114    * 
115    * <PRE>
116    * ann1 - for sequence 0 - label 'IUPRED' 
117    * ann2 - not sequence related - label 'Beauty' 
118    * ann3 - for sequence 3 - label 'JMol'
119    * ann4 - for sequence 2 - label 'IUPRED'
120    * ann5 - for sequence 1 - label 'JMol'
121    */
122   private void addAnnotations()
123   {
124     Annotation an = new Annotation(2f);
125     Annotation[] anns = new Annotation[] { an, an, an };
126     AlignmentAnnotation ann0 = new AlignmentAnnotation("IUPRED", "", anns);
127     AlignmentAnnotation ann1 = new AlignmentAnnotation("Beauty", "", anns);
128     AlignmentAnnotation ann2 = new AlignmentAnnotation("JMol", "", anns);
129     AlignmentAnnotation ann3 = new AlignmentAnnotation("IUPRED", "", anns);
130     AlignmentAnnotation ann4 = new AlignmentAnnotation("JMol", "", anns);
131     SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
132     ann0.setSequenceRef(seqs[0]);
133     ann2.setSequenceRef(seqs[3]);
134     ann3.setSequenceRef(seqs[2]);
135     ann4.setSequenceRef(seqs[1]);
136     parentPanel.getAlignment().addAnnotation(ann0);
137     parentPanel.getAlignment().addAnnotation(ann1);
138     parentPanel.getAlignment().addAnnotation(ann2);
139     parentPanel.getAlignment().addAnnotation(ann3);
140     parentPanel.getAlignment().addAnnotation(ann4);
141   }
142
143   /**
144    * Test creation of panel with OK and Cancel buttons
145    */
146   @Test(groups = { "Functional" })
147   public void testBuildActionButtonsPanel()
148   {
149     testee = new AnnotationChooser(parentPanel);
150     JPanel jp = testee.buildActionButtonsPanel();
151     assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
152
153     Component[] comps = jp.getComponents();
154     assertEquals("Not 2 action buttons", 2, comps.length);
155
156     final Component jb1 = comps[0];
157     final Component jb2 = comps[1];
158
159     assertEquals("Not 'OK' button", MessageManager.getString("action.ok"),
160             ((JButton) jb1).getText());
161     assertEquals("Wrong button font", JvSwingUtils.getLabelFont(),
162             jb1.getFont());
163
164     assertEquals("Not 'Cancel' button",
165             MessageManager.getString("action.cancel"),
166             ((JButton) jb2).getText());
167     assertEquals("Wrong button font", JvSwingUtils.getLabelFont(),
168             jb2.getFont());
169   }
170
171   /**
172    * Test 'Apply to' has 3 radio buttons enabled, 'Selected Sequences' selected,
173    * when there is a current selection group.
174    */
175   @Test(groups = { "Functional" })
176   public void testBuildApplyToOptionsPanel_withSelectionGroup()
177   {
178     selectSequences(0, 2, 3);
179     testee = new AnnotationChooser(parentPanel);
180
181     JPanel jp = testee.buildApplyToOptionsPanel();
182     Component[] comps = jp.getComponents();
183     assertEquals("Not 3 radio buttons", 3, comps.length);
184
185     final Checkbox cb1 = (Checkbox) comps[0];
186     final Checkbox cb2 = (Checkbox) comps[1];
187     final Checkbox cb3 = (Checkbox) comps[2];
188
189     assertTrue("Not enabled", cb1.isEnabled());
190     assertTrue("Not enabled", cb2.isEnabled());
191     assertTrue("Not enabled", cb3.isEnabled());
192     assertEquals("Option not selected", cb2, cb2.getCheckboxGroup()
193             .getSelectedCheckbox());
194
195     // check state variables match checkbox selection
196     assertTrue(testee.isApplyToSelectedSequences());
197     assertFalse(testee.isApplyToUnselectedSequences());
198   }
199
200   /**
201    * Add a sequence group to the alignment with the specified sequences (base 0)
202    * in it
203    * 
204    * @param i
205    * @param more
206    */
207   private void selectSequences(int... selected)
208   {
209     SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
210     SequenceGroup sg = new SequenceGroup();
211     for (int i : selected)
212     {
213       sg.addSequence(seqs[i], false);
214     }
215     parentPanel.av.setSelectionGroup(sg);
216   }
217
218   /**
219    * Test 'Apply to' has 1 radio button enabled, 'All Sequences' selected, when
220    * there is no current selection group.
221    */
222   @Test(groups = { "Functional" })
223   public void testBuildApplyToOptionsPanel_noSelectionGroup()
224   {
225     testee = new AnnotationChooser(parentPanel);
226     JPanel jp = testee.buildApplyToOptionsPanel();
227     verifyApplyToOptionsPanel_noSelectionGroup(jp);
228   }
229
230   protected void verifyApplyToOptionsPanel_noSelectionGroup(JPanel jp)
231   {
232     assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
233     Component[] comps = jp.getComponents();
234     assertEquals("Not 3 radio buttons", 3, comps.length);
235
236     final Checkbox cb1 = (Checkbox) comps[0];
237     final Checkbox cb2 = (Checkbox) comps[1];
238     final Checkbox cb3 = (Checkbox) comps[2];
239
240     assertTrue("Not enabled", cb1.isEnabled());
241     assertFalse("Enabled", cb2.isEnabled());
242     assertFalse("Enabled", cb3.isEnabled());
243     assertEquals("Not selected", cb1, cb1.getCheckboxGroup()
244             .getSelectedCheckbox());
245
246     // check state variables match checkbox selection
247     assertTrue(testee.isApplyToSelectedSequences());
248     assertTrue(testee.isApplyToUnselectedSequences());
249
250     assertEquals("Wrong text",
251             MessageManager.getString("label.all_sequences"), cb1.getLabel());
252     assertEquals("Wrong text",
253             MessageManager.getString("label.selected_sequences"),
254             cb2.getLabel());
255     assertEquals("Wrong text",
256             MessageManager.getString("label.except_selected_sequences"),
257             cb3.getLabel());
258   }
259
260   /**
261    * Test Show and Hide radio buttons created, with Hide initially selected.
262    */
263   @Test(groups = { "Functional" })
264   public void testBuildShowHidePanel()
265   {
266     testee = new AnnotationChooser(parentPanel);
267     JPanel jp = testee.buildShowHidePanel();
268     verifyShowHidePanel(jp);
269
270   }
271
272   protected void verifyShowHidePanel(JPanel jp)
273   {
274     assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
275     Component[] comps = jp.getComponents();
276     assertEquals("Not 2 radio buttons", 2, comps.length);
277
278     final Checkbox cb1 = (Checkbox) comps[0];
279     final Checkbox cb2 = (Checkbox) comps[1];
280
281     assertTrue("Show not enabled", cb1.isEnabled());
282     assertTrue("Hide not enabled", cb2.isEnabled());
283
284     // Hide (button 2) selected; note this may change to none (null)
285     assertEquals("Not selected", cb2, cb2.getCheckboxGroup()
286             .getSelectedCheckbox());
287
288     assertTrue("Show is flagged", !testee.isShowSelected());
289
290     assertEquals("Wrong text",
291             MessageManager.getString("label.show_selected_annotations"),
292             cb1.getLabel());
293     assertEquals("Wrong text",
294             MessageManager.getString("label.hide_selected_annotations"),
295             cb2.getLabel());
296   }
297
298   /**
299    * Test construction of panel containing two sub-panels
300    */
301   @Test(groups = { "Functional" })
302   public void testBuildShowHideOptionsPanel()
303   {
304     testee = new AnnotationChooser(parentPanel);
305     JPanel jp = testee.buildShowHideOptionsPanel();
306     assertTrue("Wrong layout", jp.getLayout() instanceof BorderLayout);
307     Component[] comps = jp.getComponents();
308     assertEquals("Not 2 sub-panels", 2, comps.length);
309
310     verifyShowHidePanel((JPanel) comps[0]);
311     verifyApplyToOptionsPanel_noSelectionGroup((JPanel) comps[1]);
312   }
313
314   /**
315    * Test that annotation types are (uniquely) identified.
316    * 
317    */
318   @Test(groups = { "Functional" })
319   public void testGetAnnotationTypes()
320   {
321     selectSequences(1);
322     testee = new AnnotationChooser(parentPanel);
323     // selection group should make no difference to the result
324     // as all annotation types for the alignment are considered
325
326     List<String> types = AnnotationChooser.getAnnotationTypes(
327             parentPanel.getAlignment(), true);
328     assertEquals("Not two annotation types", 2, types.size());
329     assertTrue("IUPRED missing", types.contains("IUPRED"));
330     assertTrue("JMol missing", types.contains("JMol"));
331
332     types = AnnotationChooser.getAnnotationTypes(
333             parentPanel.getAlignment(), false);
334     assertEquals("Not six annotation types", 7, types.size());
335     assertTrue("IUPRED missing", types.contains("IUPRED"));
336     assertTrue("JMol missing", types.contains("JMol"));
337     assertTrue("Beauty missing", types.contains("Beauty"));
338     // These are added by viewmodel.AlignViewport.initAutoAnnotation():
339     assertTrue("Consensus missing", types.contains("Consensus"));
340     assertTrue("Quality missing", types.contains("Quality"));
341     assertTrue("Conservation missing", types.contains("Conservation"));
342     assertTrue("Occupancy missing", types.contains("Occupancy"));
343   }
344
345   /**
346    * Test result of selecting an annotation type, with 'Hide for all sequences'.
347    * 
348    * We expect all annotations of that type to be set hidden. Other annotations
349    * should be left visible.
350    */
351   @Test(groups = { "Functional" })
352   public void testSelectType_hideForAll()
353   {
354     selectSequences(1, 2);
355     testee = new AnnotationChooser(parentPanel);
356     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
357     setSelected(hideCheckbox, true);
358
359     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
360             1, 1, 0);
361     setSelected(allSequencesCheckbox, true);
362
363     AlignmentAnnotation[] anns = parentPanel.getAlignment()
364             .getAlignmentAnnotation();
365
366     assertTrue(anns[AUTOCALCD + 2].visible); // JMol for seq3
367     assertTrue(anns[AUTOCALCD + 4].visible); // JMol for seq1
368
369     setSelected(getTypeCheckbox("JMol"), true);
370     assertTrue(anns[0].visible); // Conservation
371     assertTrue(anns[1].visible); // Quality
372     assertTrue(anns[2].visible); // Consensus
373     assertTrue(anns[3].visible); // Occupancy
374     assertTrue(anns[4].visible); // IUPred for seq0
375     assertTrue(anns[5].visible); // Beauty
376     assertFalse(anns[6].visible); // JMol for seq3 - not selected but hidden
377     assertTrue(anns[7].visible); // IUPRED for seq2
378     assertFalse(anns[8].visible); // JMol for seq1 - selected and hidden
379   }
380
381   /**
382    * Test result of selecting an annotation type, with 'Hide for selected
383    * sequences'.
384    * 
385    * We expect the annotations of that type, linked to the sequence group, to be
386    * set hidden. Other annotations should be left visible.
387    */
388   @Test(groups = { "Functional" })
389   public void testSelectType_hideForSelected()
390   {
391     selectSequences(1, 2);
392     testee = new AnnotationChooser(parentPanel);
393     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
394     setSelected(hideCheckbox, true);
395
396     /*
397      * Don't set the 'selected sequences' radio button since this would trigger
398      * an update, including unselected sequences / annotation types
399      */
400     // setSelected(getSelectedSequencesCheckbox());
401
402     AlignmentAnnotation[] anns = parentPanel.getAlignment()
403             .getAlignmentAnnotation();
404
405     assertTrue(anns[AUTOCALCD + 4].visible); // JMol for seq1
406
407     setSelected(getTypeCheckbox("JMol"), true);
408     assertTrue(anns[0].visible); // Conservation
409     assertTrue(anns[1].visible); // Quality
410     assertTrue(anns[2].visible); // Consensus
411     assertTrue(anns[3].visible); // Occupancy
412     assertTrue(anns[4].visible); // IUPred for seq0
413     assertTrue(anns[5].visible); // Beauty
414     assertTrue(anns[6].visible); // JMol for seq3 not in selection group
415     assertTrue(anns[7].visible); // IUPRED for seq2
416     assertFalse(anns[8].visible); // JMol for seq1 in selection group
417   }
418
419   /**
420    * Test result of deselecting an annotation type, with 'Hide for all
421    * sequences'.
422    * 
423    * We expect all annotations of that type to be set visible. Other annotations
424    * should be left unchanged.
425    */
426   @Test(groups = { "Functional" })
427   public void testDeselectType_hideForAll()
428   {
429     selectSequences(1, 2);
430     testee = new AnnotationChooser(parentPanel);
431
432     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
433     setSelected(hideCheckbox, true);
434
435     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
436             1, 1, 0);
437     setSelected(allSequencesCheckbox, true);
438
439     AlignmentAnnotation[] anns = parentPanel.getAlignment()
440             .getAlignmentAnnotation();
441
442     final Checkbox typeCheckbox = getTypeCheckbox("JMol");
443
444     // select JMol - all hidden
445     setSelected(typeCheckbox, true);
446     assertFalse(anns[AUTOCALCD + 2].visible); // JMol for seq3
447     assertFalse(anns[AUTOCALCD + 4].visible); // JMol for seq1
448
449     // deselect JMol - all unhidden
450     setSelected(typeCheckbox, false);
451     assertTrue(anns[0].visible); // Conservation
452     assertTrue(anns[1].visible); // Quality
453     assertTrue(anns[2].visible); // Consensus
454     assertTrue(anns[3].visible); // Occupancy
455     assertTrue(anns[4].visible); // IUPred for seq0
456     assertTrue(anns[5].visible); // Beauty
457     assertTrue(anns[6].visible); // JMol for seq3
458     assertTrue(anns[7].visible); // IUPRED for seq2
459     assertTrue(anns[8].visible); // JMol for seq1
460   }
461
462   /**
463    * Test result of deselecting an annotation type, with 'Hide for selected
464    * sequences'.
465    * 
466    * We expect the annotations of that type, linked to the sequence group, to be
467    * set visible. Other annotations should be left unchanged.
468    */
469   @Test(groups = { "Functional" })
470   public void testDeselectType_hideForSelected()
471   {
472     selectSequences(1, 2);
473     testee = new AnnotationChooser(parentPanel);
474     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
475     setSelected(hideCheckbox, true);
476
477     /*
478      * Don't set the 'selected sequences' radio button since this would trigger
479      * an update, including unselected sequences / annotation types
480      */
481     // setSelected(getSelectedSequencesCheckbox());
482
483     setSelected(getTypeCheckbox("JMol"), true);
484     setSelected(getTypeCheckbox("JMol"), false);
485
486     AlignmentAnnotation[] anns = parentPanel.getAlignment()
487             .getAlignmentAnnotation();
488     assertTrue(anns[0].visible); // Conservation
489     assertTrue(anns[1].visible); // Quality
490     assertTrue(anns[2].visible); // Consensus
491     assertTrue(anns[3].visible); // IUPred for seq0
492     assertTrue(anns[4].visible); // Beauty
493     assertTrue(anns[5].visible); // JMol for seq3 not in selection group
494     assertTrue(anns[6].visible); // IUPRED for seq2
495     assertTrue(anns[7].visible); // JMol for seq1 in selection group
496   }
497
498   /**
499    * Test result of selecting an annotation type, with 'Show for all sequences'.
500    * 
501    * We expect all annotations of that type to be set visible. Other annotations
502    * should be left unchanged
503    */
504   @Test(groups = { "Functional" })
505   public void testSelectType_showForAll()
506   {
507     selectSequences(1, 2);
508     testee = new AnnotationChooser(parentPanel);
509     final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
510     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
511
512     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
513             1, 1, 0);
514
515     AlignmentAnnotation[] anns = parentPanel.getAlignment()
516             .getAlignmentAnnotation();
517
518     // hide all JMol annotations
519     setSelected(allSequencesCheckbox, true);
520     setSelected(hideCheckbox, true);
521     setSelected(getTypeCheckbox("JMol"), true);
522     assertFalse(anns[AUTOCALCD + 2].visible); // JMol for seq3
523     assertFalse(anns[AUTOCALCD + 4].visible); // JMol for seq1
524     // ...now show them...
525     setSelected(showCheckbox, true);
526     assertTrue(anns[0].visible); // Conservation
527     assertTrue(anns[1].visible); // Quality
528     assertTrue(anns[2].visible); // Consensus
529     assertTrue(anns[3].visible); // Occupancy
530     assertTrue(anns[4].visible); // IUPred for seq0
531     assertTrue(anns[5].visible); // Beauty
532     assertTrue(anns[6].visible); // JMol for seq3
533     assertTrue(anns[7].visible); // IUPRED for seq2
534     assertTrue(anns[8].visible); // JMol for seq1
535   }
536
537   /**
538    * Test result of selecting an annotation type, with 'Show for selected
539    * sequences'.
540    * 
541    * We expect all annotations of that type, linked to the sequence group, to be
542    * set visible. Other annotations should be left unchanged
543    */
544   @Test(groups = { "Functional" })
545   public void testSelectType_showForSelected()
546   {
547     // sequences 1 and 2 have annotations IUPred and Jmol
548     selectSequences(1, 2);
549     testee = new AnnotationChooser(parentPanel);
550     final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
551     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
552
553     final Checkbox selectedSequencesCheckbox = (Checkbox) getComponent(
554             testee, 1, 1, 1);
555
556     AlignmentAnnotation[] anns = parentPanel.getAlignment()
557             .getAlignmentAnnotation();
558
559     // hide all JMol annotations in the selection region (== annotation 7)
560     setSelected(selectedSequencesCheckbox, true);
561     setSelected(hideCheckbox, true);
562     setSelected(getTypeCheckbox("JMol"), true);
563
564     assertTrue(anns[AUTOCALCD + 2].visible); // JMol for seq3
565     assertFalse(anns[AUTOCALCD + 4].visible); // JMol for seq1
566     // ...now show them...
567     setSelected(showCheckbox, true);
568
569     assertTrue(anns[0].visible); // Conservation
570     assertTrue(anns[1].visible); // Quality
571     assertTrue(anns[2].visible); // Consensus
572     assertTrue(anns[3].visible); // Occupancy
573     assertTrue(anns[4].visible); // IUPred for seq0
574     assertTrue(anns[5].visible); // Beauty
575     assertTrue(anns[6].visible); // JMol for seq3
576     assertTrue(anns[7].visible); // IUPRED for seq2
577     assertTrue(anns[8].visible); // JMol for seq1
578   }
579
580   /**
581    * Test result of deselecting an annotation type, with 'Show for all
582    * sequences'.
583    * 
584    * We expect all annotations of that type to be set hidden. Other annotations
585    * should be left unchanged.
586    */
587   @Test(groups = { "Functional" })
588   public void testDeselectType_showForAll()
589   {
590     selectSequences(1, 2);
591     testee = new AnnotationChooser(parentPanel);
592
593     final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
594     setSelected(showCheckbox, true);
595
596     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
597             1, 1, 0);
598     setSelected(allSequencesCheckbox, true);
599
600     AlignmentAnnotation[] anns = parentPanel.getAlignment()
601             .getAlignmentAnnotation();
602
603     final Checkbox typeCheckbox = getTypeCheckbox("JMol");
604     // select JMol - all shown
605     setSelected(typeCheckbox, true);
606     assertTrue(anns[AUTOCALCD + 2].visible); // JMol for seq3
607     assertTrue(anns[AUTOCALCD + 4].visible); // JMol for seq1
608
609     // deselect JMol - all hidden
610     setSelected(typeCheckbox, false);
611     assertTrue(anns[0].visible); // Conservation
612     assertTrue(anns[1].visible); // Quality
613     assertTrue(anns[2].visible); // Consensus
614     assertTrue(anns[3].visible); // Occupancy
615     assertTrue(anns[4].visible); // IUPred for seq0
616     assertTrue(anns[5].visible); // Beauty
617     assertFalse(anns[6].visible); // JMol for seq3
618     assertTrue(anns[7].visible); // IUPRED for seq2
619     assertFalse(anns[8].visible); // JMol for seq1
620   }
621
622   /**
623    * Test result of deselecting an annotation type, with 'Show for selected
624    * sequences'.
625    * 
626    * We expect the annotations of that type, linked to the sequence group, to be
627    * set hidden. Other annotations should be left unchanged.
628    */
629   @Test(groups = { "Functional" })
630   public void testDeselectType_showForSelected()
631   {
632     selectSequences(1, 2);
633     testee = new AnnotationChooser(parentPanel);
634     final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
635     setSelected(showCheckbox, true);
636
637     /*
638      * Don't set the 'selected sequences' radio button since this would trigger
639      * an update, including unselected sequences / annotation types
640      */
641     // setSelected(getSelectedSequencesCheckbox());
642
643     AlignmentAnnotation[] anns = parentPanel.getAlignment()
644             .getAlignmentAnnotation();
645
646     // select JMol - should remain visible
647     setSelected(getTypeCheckbox("JMol"), true);
648     assertTrue(anns[AUTOCALCD + 2].visible); // JMol for seq3
649     assertTrue(anns[AUTOCALCD + 4].visible); // JMol for seq1
650
651     // deselect JMol - should be hidden for selected sequences only
652     setSelected(getTypeCheckbox("JMol"), false);
653     assertTrue(anns[0].visible); // Conservation
654     assertTrue(anns[1].visible); // Quality
655     assertTrue(anns[2].visible); // Consensus
656     assertTrue(anns[3].visible); // Occupancy
657     assertTrue(anns[4].visible); // IUPred for seq0
658     assertTrue(anns[5].visible); // Beauty
659     assertTrue(anns[6].visible); // JMol for seq3 not in selection group
660     assertTrue(anns[7].visible); // IUPRED for seq2
661     assertFalse(anns[8].visible); // JMol for seq1 in selection group
662   }
663
664   /**
665    * Helper method to drill down to a sub-component in a Container hierarchy.
666    * 
667    * @param cont
668    * @param i
669    * @param j
670    * @param k
671    * @return
672    */
673   public static Component getComponent(Container cont, int... positions)
674   {
675     Component comp = cont;
676     for (int i : positions)
677     {
678       comp = ((Container) comp).getComponent(i);
679     }
680     return comp;
681   }
682
683   /**
684    * Helper method to set or unset a checkbox and fire its action listener.
685    * 
686    * @param cb
687    * @param select
688    */
689   protected void setSelected(Checkbox cb, boolean select)
690   {
691     // TODO refactor to a test utility class
692     cb.setState(select);
693     // have to manually fire the action listener
694     cb.getItemListeners()[0].itemStateChanged(new ItemEvent(cb,
695             ItemEvent.ITEM_STATE_CHANGED, cb, select ? ItemEvent.SELECTED
696                     : ItemEvent.DESELECTED));
697   }
698
699   /**
700    * Helper method to drill down to the 'Annotation type' checkbox with given
701    * label.
702    * 
703    * @return
704    */
705   private Checkbox getTypeCheckbox(String forLabel)
706   {
707     Component[] cbs = ((JPanel) testee.getComponent(0)).getComponents();
708     for (Component comp : cbs)
709     {
710       final Checkbox cb = (Checkbox) comp;
711       if (cb.getLabel().equals(forLabel))
712       {
713         return cb;
714       }
715     }
716     return null;
717   }
718
719   /**
720    * Test isInActionScope for the case where the scope is selected sequences.
721    * Test cases include sequences in the selection group, and others not in the
722    * group.
723    */
724   @Test(groups = { "Functional" })
725   public void testIsInActionScope_selectedScope()
726   {
727     // sequences 1 and 2 have annotations 4 and 3 respectively
728     selectSequences(1, 2);
729     testee = new AnnotationChooser(parentPanel);
730
731     final Checkbox selectedSequencesCheckbox = (Checkbox) getComponent(
732             testee, 1, 1, 1);
733     setSelected(selectedSequencesCheckbox, true);
734
735     AlignmentAnnotation[] anns = parentPanel.getAlignment()
736             .getAlignmentAnnotation();
737     assertFalse(testee.isInActionScope(anns[AUTOCALCD]));
738     assertFalse(testee.isInActionScope(anns[AUTOCALCD + 1]));
739     assertFalse(testee.isInActionScope(anns[AUTOCALCD + 2]));
740     assertTrue(testee.isInActionScope(anns[AUTOCALCD + 3]));
741     assertTrue(testee.isInActionScope(anns[AUTOCALCD + 4]));
742   }
743
744   /**
745    * Test isInActionScope for the case where the scope is unselected sequences.
746    * Test cases include sequences in the selection group, and others not in the
747    * group.
748    */
749   @Test(groups = { "Functional" })
750   public void testIsInActionScope_unselectedScope()
751   {
752     // sequences 1 and 2 have annotations 4 and 3 respectively
753     selectSequences(1, 2);
754     testee = new AnnotationChooser(parentPanel);
755
756     final Checkbox unselectedSequencesCheckbox = (Checkbox) getComponent(
757             testee, 1, 1, 2);
758     setSelected(unselectedSequencesCheckbox, true);
759
760     AlignmentAnnotation[] anns = parentPanel.getAlignment()
761             .getAlignmentAnnotation();
762     assertTrue(testee.isInActionScope(anns[AUTOCALCD]));
763     assertTrue(testee.isInActionScope(anns[AUTOCALCD + 1]));
764     assertTrue(testee.isInActionScope(anns[AUTOCALCD + 2]));
765     assertFalse(testee.isInActionScope(anns[AUTOCALCD + 3]));
766     assertFalse(testee.isInActionScope(anns[AUTOCALCD + 4]));
767   }
768
769   /**
770    * Test that the reset method restores previous visibility flags.
771    */
772   @Test(groups = { "Functional" })
773   public void testResetOriginalState()
774   {
775     testee = new AnnotationChooser(parentPanel);
776
777     AlignmentAnnotation[] anns = parentPanel.getAlignment()
778             .getAlignmentAnnotation();
779     // all start visible
780     for (int i = 0; i < anns.length; i++)
781     {
782       assertTrue(i + "'th sequence not visible", anns[i].visible);
783     }
784
785     /*
786      * check options to hide JMol and IUPRED annotations for all sequences
787      */
788     final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
789     setSelected(hideCheckbox, true);
790
791     final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
792             1, 1, 0);
793     setSelected(allSequencesCheckbox, true);
794
795     setSelected(getTypeCheckbox("JMol"), true);
796     setSelected(getTypeCheckbox("IUPRED"), true);
797
798     assertTrue(anns[0].visible); // Conservation
799     assertTrue(anns[1].visible); // Quality
800     assertTrue(anns[2].visible); // Consensus
801     assertTrue(anns[3].visible); // Occupancy
802     assertFalse(anns[4].visible); // IUPRED
803     assertTrue(anns[5].visible); // Beauty (not seq-related)
804     assertFalse(anns[6].visible); // JMol
805     assertFalse(anns[7].visible); // IUPRED
806     assertFalse(anns[8].visible); // JMol
807
808     // reset - should all be visible
809     testee.resetOriginalState();
810     for (int i = 0; i < anns.length; i++)
811     {
812       assertTrue(i + "'th sequence not visible", anns[i].visible);
813     }
814   }
815 }