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