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