+ /*
+ * if sequence is null, only feature links are shown (alignment popup submenu)
+ */
+ linkMenu = PopupMenu.buildLinkMenu(null, noFeatures);
+ linkItems = linkMenu.getMenuComponents();
+ assertEquals(0, linkItems.length);
+
+ List<SequenceFeature> features = new ArrayList<>();
+ SequenceFeature sf = new SequenceFeature("type", "desc", 1, 20, null);
+ features.add(sf);
+ linkMenu = PopupMenu.buildLinkMenu(null, features);
+ linkItems = linkMenu.getMenuComponents();
+ assertEquals(0, linkItems.length); // feature has no links
+
+ sf.addLink("Pfam family|http://pfam.xfam.org/family/PF00111");
+ linkMenu = PopupMenu.buildLinkMenu(null, features);
+ linkItems = linkMenu.getMenuComponents();
+ assertEquals(1, linkItems.length);
+ JMenuItem item = (JMenuItem) linkItems[0];
+ assertEquals("Pfam family", item.getText());
+ // ? no way to verify URL, compiled into link's actionListener
+ }
+
+ @Test(groups = { "Functional" })
+ public void testHideInsertions()
+ {
+ // get sequences from the alignment
+ List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
+
+ // add our own seqs to avoid problems with changes to existing sequences
+ // (gap at end of sequences varies depending on how tests are run!)
+ Sequence seqGap1 = new Sequence("GappySeq",
+ "AAAA----AA-AAAAAAA---AAA-----------AAAAAAAAAA--");
+ seqGap1.createDatasetSequence();
+ seqs.add(seqGap1);
+ Sequence seqGap2 = new Sequence("LessGappySeq",
+ "AAAAAA-AAAAA---AAA--AAAAA--AAAAAAA-AAAAAA");
+ seqGap2.createDatasetSequence();
+ seqs.add(seqGap2);
+ Sequence seqGap3 = new Sequence("AnotherGapSeq",
+ "AAAAAA-AAAAAA--AAAAAA-AAAAAAAAAAA---AAAAAAAA");
+ seqGap3.createDatasetSequence();
+ seqs.add(seqGap3);
+ Sequence seqGap4 = new Sequence("NoGaps",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+ seqGap4.createDatasetSequence();
+ seqs.add(seqGap4);
+
+ ColumnSelection sel = new ColumnSelection();
+ parentPanel.av.getAlignment().getHiddenColumns()
+ .revealAllHiddenColumns(sel);
+
+ // get the Popup Menu for 7th sequence - no insertions
+ testee = new PopupMenu(parentPanel, seqs.get(7), null);
+ testee.hideInsertions_actionPerformed(null);
+
+ HiddenColumns hidden = parentPanel.av.getAlignment().getHiddenColumns();
+ Iterator<int[]> it = hidden.iterator();
+ assertFalse(it.hasNext());
+
+ // get the Popup Menu for GappySeq - this time we have insertions
+ testee = new PopupMenu(parentPanel, seqs.get(4), null);
+ testee.hideInsertions_actionPerformed(null);
+ hidden = parentPanel.av.getAlignment().getHiddenColumns();
+ it = hidden.iterator();
+
+ assertTrue(it.hasNext());
+ int[] region = it.next();
+ assertEquals(region[0], 4);
+ assertEquals(region[1], 7);
+
+ assertTrue(it.hasNext());
+ region = it.next();
+ assertEquals(region[0], 10);
+ assertEquals(region[1], 10);
+
+ assertTrue(it.hasNext());
+ region = it.next();
+ assertEquals(region[0], 18);
+ assertEquals(region[1], 20);
+
+ assertTrue(it.hasNext());
+ region = it.next();
+ assertEquals(region[0], 24);
+ assertEquals(region[1], 34);
+
+ assertTrue(it.hasNext());
+ region = it.next();
+ assertEquals(region[0], 45);
+ assertEquals(region[1], 46);
+
+ assertFalse(it.hasNext());
+
+ sel = new ColumnSelection();
+ hidden.revealAllHiddenColumns(sel);
+
+ // make a sequence group and hide insertions within the group
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(8);
+ sg.setEndRes(42);
+ sg.addSequence(seqGap2, false);
+ sg.addSequence(seqGap3, false);
+ parentPanel.av.setSelectionGroup(sg);
+
+ // hide columns outside and within selection
+ // only hidden columns outside the collection will be retained (unless also
+ // gaps in the selection)
+ hidden.hideColumns(1, 10);
+ hidden.hideColumns(31, 40);
+
+ // get the Popup Menu for LessGappySeq in the sequence group
+ testee = new PopupMenu(parentPanel, seqs.get(5), null);
+ testee.hideInsertions_actionPerformed(null);
+ hidden = parentPanel.av.getAlignment().getHiddenColumns();
+ it = hidden.iterator();
+
+ assertTrue(it.hasNext());
+ region = it.next();
+ assertEquals(region[0], 1);
+ assertEquals(region[1], 7);
+
+ assertTrue(it.hasNext());
+ region = it.next();
+ assertEquals(region[0], 13);
+ assertEquals(region[1], 14);
+
+ assertTrue(it.hasNext());
+ region = it.next();
+ assertEquals(region[0], 34);
+ assertEquals(region[1], 34);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testAddFeatureDetails()
+ {
+ String menuText = MessageManager.getString("label.feature_details");
+
+ /*
+ * with no features, sub-menu should not be created
+ */
+ List<SequenceFeature> features = new ArrayList<>();
+ SequenceI seq = this.alignment.getSequenceAt(0); // FER_CAPAA/1-12
+ testee.addFeatureDetails(features, seq, 10);
+ JMenu menu = findMenu(testee, menuText);
+ assertNull(menu);
+
+ /*
+ * add some features; the menu item text is wrapped in html, and includes
+ * feature type, position, description, group (if not null)
+ */
+ SequenceFeature sf1 = new SequenceFeature("helix", "curly", 2, 6, null);
+ SequenceFeature sf2 = new SequenceFeature("chain", "straight", 1, 1,
+ "uniprot");
+ features.add(sf1);
+ features.add(sf2);
+ testee.addFeatureDetails(features, seq, 10);
+ menu = findMenu(testee, menuText);
+ assertNotNull(menu);
+ assertEquals(2, menu.getItemCount());
+ JMenuItem item = menu.getItem(0);
+ assertEquals("<html>helix 2-6 curly</html>", item.getText());
+ item = menu.getItem(1);
+ assertEquals("<html>chain 1 straight (uniprot)</html>", item.getText());
+
+ /*
+ * long feature descriptions are truncated to 40 characters
+ */
+ sf1.setDescription("this is a quite extraordinarily long description");
+ testee.remove(menu); // don't create the sub-menu twice
+ testee.addFeatureDetails(features, seq, 10);
+ menu = findMenu(testee, menuText);
+ item = menu.getItem(0);
+ assertEquals(
+ "<html>helix 2-6 this is a quite extraordinarily long des...</html>",
+ item.getText());
+ }
+
+ /**
+ * Returns the first component which is a JMenu with the given text
+ *
+ * @param c
+ * @param text
+ * @return
+ */
+ private JMenu findMenu(Container c, String text)
+ {
+ for (int i = 0; i < c.getComponentCount(); i++)