Merge branch 'develop' into features/JAL-2446NCList
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 8 May 2017 16:01:31 +0000 (17:01 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 8 May 2017 16:01:31 +0000 (17:01 +0100)
Conflicts:
src/jalview/appletgui/IdPanel.java
src/jalview/gui/FeatureRenderer.java

1  2 
src/jalview/appletgui/IdPanel.java
src/jalview/gui/FeatureRenderer.java

@@@ -20,6 -20,7 +20,6 @@@
   */
  package jalview.appletgui;
  
 -import jalview.datamodel.Sequence;
  import jalview.datamodel.SequenceFeature;
  import jalview.datamodel.SequenceGroup;
  import jalview.datamodel.SequenceI;
@@@ -34,6 -35,7 +34,7 @@@ import java.awt.event.InputEvent
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseListener;
  import java.awt.event.MouseMotionListener;
+ import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  
@@@ -55,11 -57,11 +56,11 @@@ public class IdPanel extends Panel impl
  
    UrlProviderI urlProvider = null;
  
--  public IdPanel(AlignViewport av, AlignmentPanel parent)
++  public IdPanel(AlignViewport viewport, AlignmentPanel parent)
    {
--    this.av = av;
++    this.av = viewport;
      alignPanel = parent;
--    idCanvas = new IdCanvas(av);
++    idCanvas = new IdCanvas(viewport);
      setLayout(new BorderLayout());
      add(idCanvas, BorderLayout.CENTER);
      idCanvas.addMouseListener(this);
  
      // make a list of label,url pairs
      HashMap<String, String> urlList = new HashMap<String, String>();
--    if (av.applet != null)
++    if (viewport.applet != null)
      {
        for (int i = 1; i < 10; i++)
        {
--        label = av.applet.getParameter("linkLabel_" + i);
--        url = av.applet.getParameter("linkURL_" + i);
++        label = viewport.applet.getParameter("linkLabel_" + i);
++        url = viewport.applet.getParameter("linkURL_" + i);
  
          // only add non-null parameters
          if (label != null)
@@@ -87,7 -89,7 +88,7 @@@
        if (!urlList.isEmpty())
        {
          // set default as first entry in list
--        String defaultUrl = av.applet.getParameter("linkLabel_1");
++        String defaultUrl = viewport.applet.getParameter("linkLabel_1");
          UrlProviderFactoryI factory = new AppletUrlProviderFactory(
                  defaultUrl, urlList);
          urlProvider = factory.createUrlProvider();
  
      SequenceI sequence = av.getAlignment().getSequenceAt(seq);
  
 -    // look for non-pos features
      StringBuffer tooltiptext = new StringBuffer();
 -    if (sequence != null)
 +    if (sequence == null)
      {
 -      if (sequence.getDescription() != null)
 +      return;
 +    }
 +    if (sequence.getDescription() != null)
 +    {
 +      tooltiptext.append(sequence.getDescription());
 +      tooltiptext.append("\n");
 +    }
 +
 +    for (SequenceFeature sf : sequence.getFeatures()
 +            .getNonPositionalFeatures())
 +    {
 +      boolean nl = false;
 +      if (sf.getFeatureGroup() != null)
        {
 -        tooltiptext.append(sequence.getDescription());
 -        tooltiptext.append("\n");
 +        tooltiptext.append(sf.getFeatureGroup());
 +        nl = true;
        }
 -
 -      SequenceFeature sf[] = sequence.getSequenceFeatures();
 -      for (int sl = 0; sf != null && sl < sf.length; sl++)
 +      if (sf.getType() != null)
        {
 -        if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0)
 -        {
 -          boolean nl = false;
 -          if (sf[sl].getFeatureGroup() != null)
 -          {
 -            tooltiptext.append(sf[sl].getFeatureGroup());
 -            nl = true;
 -          }
 -          ;
 -          if (sf[sl].getType() != null)
 -          {
 -            tooltiptext.append(" ");
 -            tooltiptext.append(sf[sl].getType());
 -            nl = true;
 -          }
 -          ;
 -          if (sf[sl].getDescription() != null)
 -          {
 -            tooltiptext.append(" ");
 -            tooltiptext.append(sf[sl].getDescription());
 -            nl = true;
 -          }
 -          ;
 -          if (!Float.isNaN(sf[sl].getScore()) && sf[sl].getScore() != 0f)
 -          {
 -            tooltiptext.append(" Score = ");
 -            tooltiptext.append(sf[sl].getScore());
 -            nl = true;
 -          }
 -          ;
 -          if (sf[sl].getStatus() != null && sf[sl].getStatus().length() > 0)
 -          {
 -            tooltiptext.append(" (");
 -            tooltiptext.append(sf[sl].getStatus());
 -            tooltiptext.append(")");
 -            nl = true;
 -          }
 -          ;
 -          if (nl)
 -          {
 -            tooltiptext.append("\n");
 -          }
 -        }
 +        tooltiptext.append(" ");
 +        tooltiptext.append(sf.getType());
 +        nl = true;
 +      }
 +      if (sf.getDescription() != null)
 +      {
 +        tooltiptext.append(" ");
 +        tooltiptext.append(sf.getDescription());
 +        nl = true;
 +      }
 +      if (!Float.isNaN(sf.getScore()) && sf.getScore() != 0f)
 +      {
 +        tooltiptext.append(" Score = ");
 +        tooltiptext.append(sf.getScore());
 +        nl = true;
 +      }
 +      if (sf.getStatus() != null && sf.getStatus().length() > 0)
 +      {
 +        tooltiptext.append(" (");
 +        tooltiptext.append(sf.getStatus());
 +        tooltiptext.append(")");
 +        nl = true;
 +      }
 +      if (nl)
 +      {
 +        tooltiptext.append("\n");
        }
      }
 +
      if (tooltiptext.length() == 0)
      {
        // nothing to display - so clear tooltip if one is visible
      String id = sq.getName();
  
      // get the default url with the sequence details filled in
+     if (urlProvider == null)
+     {
+       return;
+     }
      String url = urlProvider.getPrimaryUrl(id);
      String target = urlProvider.getPrimaryTarget(id);
      try
  
      if ((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
      {
 -      Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq);
 +      SequenceI sq = av.getAlignment().getSequenceAt(seq);
  
 -      // build a new links menu based on the current links + any non-positional
 -      // features
 +      /*
 +       *  build a new links menu based on the current links
 +       *  and any non-positional features
 +       */
-       List<String> nlinks = urlProvider.getLinksForMenu();
+       List<String> nlinks;
+       if (urlProvider != null)
+       {
+         nlinks = urlProvider.getLinksForMenu();
+       }
+       else
+       {
+         nlinks = new ArrayList<String>();
+       }
 -      SequenceFeature sf[] = sq == null ? null : sq.getSequenceFeatures();
 -      for (int sl = 0; sf != null && sl < sf.length; sl++)
 +
 +      for (SequenceFeature sf : sq.getFeatures().getNonPositionalFeatures())
        {
 -        if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0)
 +        if (sf.links != null)
          {
 -          if (sf[sl].links != null && sf[sl].links.size() > 0)
 +          for (String link : sf.links)
            {
 -            for (int l = 0, lSize = sf[sl].links.size(); l < lSize; l++)
 -            {
 -              nlinks.add(sf[sl].links.elementAt(l));
 -            }
 +            nlinks.add(link);
            }
          }
        }
  
      boolean up = true;
  
--    public ScrollThread(boolean up)
++    public ScrollThread(boolean isUp)
      {
--      this.up = up;
++      this.up = isUp;
        start();
      }
  
@@@ -25,6 -25,7 +25,7 @@@ import jalview.datamodel.SearchResults
  import jalview.datamodel.SearchResultsI;
  import jalview.datamodel.SequenceFeature;
  import jalview.datamodel.SequenceI;
+ import jalview.io.FeaturesFile;
  import jalview.schemes.FeatureColour;
  import jalview.util.ColorUtils;
  import jalview.util.MessageManager;
@@@ -42,7 -43,7 +43,8 @@@ import java.awt.event.MouseAdapter
  import java.awt.event.MouseEvent;
  import java.util.Arrays;
  import java.util.Comparator;
 +import java.util.HashMap;
+ import java.util.List;
  
  import javax.swing.JColorChooser;
  import javax.swing.JComboBox;
@@@ -68,20 -69,19 +70,19 @@@ public class FeatureRenderer extend
    AlignmentPanel ap;
  
    /**
-    * Creates a new FeatureRenderer object.
+    * Creates a new FeatureRenderer object
     * 
-    * @param av
-    *          DOCUMENT ME!
+    * @param alignPanel
     */
-   public FeatureRenderer(AlignmentPanel ap)
+   public FeatureRenderer(AlignmentPanel alignPanel)
    {
-     super(ap.av);
-     this.ap = ap;
-     if (ap != null && ap.getSeqPanel() != null
-             && ap.getSeqPanel().seqCanvas != null
-             && ap.getSeqPanel().seqCanvas.fr != null)
+     super(alignPanel.av);
+     this.ap = alignPanel;
+     if (alignPanel.getSeqPanel() != null
+             && alignPanel.getSeqPanel().seqCanvas != null
+             && alignPanel.getSeqPanel().seqCanvas.fr != null)
      {
-       transferSettings(ap.getSeqPanel().seqCanvas.fr);
+       transferSettings(alignPanel.getSeqPanel().seqCanvas.fr);
      }
    }
  
  
    int featureIndex = 0;
  
-   boolean amendFeatures(final SequenceI[] sequences,
-           final SequenceFeature[] features, boolean newFeatures,
-           final AlignmentPanel ap)
+   /**
+    * Presents a dialog allowing the user to add new features, or amend or delete
+    * existing features. Currently this can be on
+    * <ul>
+    * <li>double-click on a sequence - Amend/Delete features at position</li>
+    * <li>Create sequence feature from pop-up menu on selected region</li>
+    * <li>Create features for pattern matches from Find</li>
+    * </ul>
+    * 
+    * @param sequences
+    *          the sequences features are to be created on (if creating
+    *          features), or a single sequence (if amending features)
+    * @param features
+    *          the current features at the position (if amending), or template
+    *          new features with start/end position set (if creating)
+    * @param create
+    *          true to create features, false to amend or delete
+    * @param featureType
+    *          the feature type to set on new features; if null, defaults to the
+    *          type of the last new feature created if any, failing that to
+    *          "feature_1"
+    * @param alignPanel
+    * @return
+    */
+   protected boolean amendFeatures(final List<SequenceI> sequences,
+           final List<SequenceFeature> features, boolean create,
+           final AlignmentPanel alignPanel, String featureType)
    {
  
      featureIndex = 0;
  
-     final JPanel bigPanel = new JPanel(new BorderLayout());
-     final JComboBox overlaps;
+     final JPanel mainPanel = new JPanel(new BorderLayout());
      final JTextField name = new JTextField(25);
      final JTextField source = new JTextField(25);
      final JTextArea description = new JTextArea(3, 25);
            if (col != null)
            {
              fcol = new FeatureColour(col);
-             updateColourButton(bigPanel, colour, new FeatureColour(col));
+             updateColourButton(mainPanel, colour, new FeatureColour(col));
            }
          }
          else
          {
            if (fcc == null)
            {
-             final String type = features[featureIndex].getType();
+             final String ft = features.get(featureIndex).getType();
+             final String type = ft == null ? lastFeatureAdded : ft;
              fcc = new FeatureColourChooser(me, type);
              fcc.setRequestFocusEnabled(true);
              fcc.requestFocus();
                  fcol = fcc.getLastColour();
                  fcc = null;
                  setColour(type, fcol);
-                 updateColourButton(bigPanel, colour, fcol);
+                 updateColourButton(mainPanel, colour, fcol);
                }
              });
  
          }
        }
      });
-     JPanel tmp = new JPanel();
-     JPanel panel = new JPanel(new GridLayout(3, 1));
+     JPanel gridPanel = new JPanel(new GridLayout(3, 1));
  
-     // /////////////////////////////////////
-     // /MULTIPLE FEATURES AT SELECTED RESIDUE
-     if (!newFeatures && features.length > 1)
+     if (!create && features.size() > 1)
      {
-       panel = new JPanel(new GridLayout(4, 1));
-       tmp = new JPanel();
-       tmp.add(new JLabel(MessageManager.getString("label.select_feature")
+       /*
+        * more than one feature at selected position - add a drop-down
+        * to choose the feature to amend
+        */
+       gridPanel = new JPanel(new GridLayout(4, 1));
+       JPanel choosePanel = new JPanel();
+       choosePanel.add(new JLabel(MessageManager
+               .getString("label.select_feature")
                + ":"));
-       overlaps = new JComboBox();
-       for (int i = 0; i < features.length; i++)
+       final JComboBox<String> overlaps = new JComboBox<String>();
+       for (SequenceFeature sf : features)
        {
-         overlaps.addItem(features[i].getType() + "/"
-                 + features[i].getBegin() + "-" + features[i].getEnd()
-                 + " (" + features[i].getFeatureGroup() + ")");
+         String text = sf.getType() + "/" + sf.getBegin() + "-"
+                 + sf.getEnd() + " (" + sf.getFeatureGroup() + ")";
+         overlaps.addItem(text);
        }
-       tmp.add(overlaps);
+       choosePanel.add(overlaps);
  
        overlaps.addItemListener(new ItemListener()
        {
            if (index != -1)
            {
              featureIndex = index;
-             name.setText(features[index].getType());
-             description.setText(features[index].getDescription());
-             source.setText(features[index].getFeatureGroup());
-             start.setValue(new Integer(features[index].getBegin()));
-             end.setValue(new Integer(features[index].getEnd()));
+             SequenceFeature sf = features.get(index);
+             name.setText(sf.getType());
+             description.setText(sf.getDescription());
+             source.setText(sf.getFeatureGroup());
+             start.setValue(new Integer(sf.getBegin()));
+             end.setValue(new Integer(sf.getEnd()));
  
              SearchResultsI highlight = new SearchResults();
-             highlight.addResult(sequences[0], features[index].getBegin(),
-                     features[index].getEnd());
+             highlight.addResult(sequences.get(0), sf.getBegin(),
+                     sf.getEnd());
  
-             ap.getSeqPanel().seqCanvas.highlightSearchResults(highlight);
+             alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(highlight);
  
            }
            FeatureColourI col = getFeatureStyle(name.getText());
                      .createColourFromName(name.getText()));
            }
            oldcol = fcol = col;
-           updateColourButton(bigPanel, colour, col);
+           updateColourButton(mainPanel, colour, col);
          }
        });
  
-       panel.add(tmp);
+       gridPanel.add(choosePanel);
      }
      // ////////
      // ////////////////////////////////////
  
-     tmp = new JPanel();
-     panel.add(tmp);
-     tmp.add(new JLabel(MessageManager.getString("label.name:"),
+     JPanel namePanel = new JPanel();
+     gridPanel.add(namePanel);
+     namePanel.add(new JLabel(MessageManager.getString("label.name:"),
              JLabel.RIGHT));
-     tmp.add(name);
+     namePanel.add(name);
  
-     tmp = new JPanel();
-     panel.add(tmp);
-     tmp.add(new JLabel(MessageManager.getString("label.group:"),
+     JPanel groupPanel = new JPanel();
+     gridPanel.add(groupPanel);
+     groupPanel.add(new JLabel(MessageManager.getString("label.group:"),
              JLabel.RIGHT));
-     tmp.add(source);
+     groupPanel.add(source);
  
-     tmp = new JPanel();
-     panel.add(tmp);
-     tmp.add(new JLabel(MessageManager.getString("label.colour"),
+     JPanel colourPanel = new JPanel();
+     gridPanel.add(colourPanel);
+     colourPanel.add(new JLabel(MessageManager.getString("label.colour"),
              JLabel.RIGHT));
-     tmp.add(colour);
+     colourPanel.add(colour);
      colour.setPreferredSize(new Dimension(150, 15));
      colour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 9));
      colour.setForeground(Color.black);
      colour.setVerticalAlignment(SwingConstants.CENTER);
      colour.setHorizontalTextPosition(SwingConstants.CENTER);
      colour.setVerticalTextPosition(SwingConstants.CENTER);
-     bigPanel.add(panel, BorderLayout.NORTH);
+     mainPanel.add(gridPanel, BorderLayout.NORTH);
  
-     panel = new JPanel();
-     panel.add(new JLabel(MessageManager.getString("label.description:"),
+     JPanel descriptionPanel = new JPanel();
+     descriptionPanel.add(new JLabel(MessageManager
+             .getString("label.description:"),
              JLabel.RIGHT));
      description.setFont(JvSwingUtils.getTextAreaFont());
      description.setLineWrap(true);
-     panel.add(new JScrollPane(description));
+     descriptionPanel.add(new JScrollPane(description));
  
-     if (!newFeatures)
+     if (!create)
      {
-       bigPanel.add(panel, BorderLayout.SOUTH);
+       mainPanel.add(descriptionPanel, BorderLayout.SOUTH);
  
-       panel = new JPanel();
-       panel.add(new JLabel(MessageManager.getString("label.start"),
+       JPanel startEndPanel = new JPanel();
+       startEndPanel.add(new JLabel(MessageManager.getString("label.start"),
                JLabel.RIGHT));
-       panel.add(start);
-       panel.add(new JLabel(MessageManager.getString("label.end"),
+       startEndPanel.add(start);
+       startEndPanel.add(new JLabel(MessageManager.getString("label.end"),
                JLabel.RIGHT));
-       panel.add(end);
-       bigPanel.add(panel, BorderLayout.CENTER);
+       startEndPanel.add(end);
+       mainPanel.add(startEndPanel, BorderLayout.CENTER);
      }
      else
      {
-       bigPanel.add(panel, BorderLayout.CENTER);
+       mainPanel.add(descriptionPanel, BorderLayout.CENTER);
      }
  
-     if (lastFeatureAdded == null)
+     SequenceFeature firstFeature = features.get(0);
+     if (featureType != null)
      {
-       if (features[0].type != null)
-       {
-         lastFeatureAdded = features[0].type;
-       }
-       else
+       lastFeatureAdded = featureType;
+     }
+     else
+     {
+       if (lastFeatureAdded == null)
        {
-         lastFeatureAdded = "feature_1";
+         if (firstFeature.type != null)
+         {
+           lastFeatureAdded = firstFeature.type;
+         }
+         else
+         {
+           lastFeatureAdded = "feature_1";
+         }
        }
      }
  
      if (lastFeatureGroupAdded == null)
      {
-       if (features[0].featureGroup != null)
+       if (firstFeature.featureGroup != null)
        {
-         lastFeatureGroupAdded = features[0].featureGroup;
+         lastFeatureGroupAdded = firstFeature.featureGroup;
        }
        else
        {
        }
      }
  
-     if (newFeatures)
+     if (create)
      {
        name.setText(lastFeatureAdded);
        source.setText(lastFeatureGroupAdded);
      }
      else
      {
-       name.setText(features[0].getType());
-       source.setText(features[0].getFeatureGroup());
+       name.setText(firstFeature.getType());
+       source.setText(firstFeature.getFeatureGroup());
      }
  
-     start.setValue(new Integer(features[0].getBegin()));
-     end.setValue(new Integer(features[0].getEnd()));
-     description.setText(features[0].getDescription());
-     updateColourButton(bigPanel, colour,
+     start.setValue(new Integer(firstFeature.getBegin()));
+     end.setValue(new Integer(firstFeature.getEnd()));
+     description.setText(firstFeature.getDescription());
+     updateColourButton(mainPanel, colour,
              (oldcol = fcol = getFeatureStyle(name.getText())));
      Object[] options;
-     if (!newFeatures)
+     if (!create)
      {
-       options = new Object[] { "Amend", "Delete", "Cancel" };
+       options = new Object[] { MessageManager.getString("label.amend"),
+           MessageManager.getString("action.delete"),
+           MessageManager.getString("action.cancel") };
      }
      else
      {
-       options = new Object[] { "OK", "Cancel" };
+       options = new Object[] { MessageManager.getString("action.ok"),
+           MessageManager.getString("action.cancel") };
      }
  
-     String title = newFeatures ? MessageManager
+     String title = create ? MessageManager
              .getString("label.create_new_sequence_features")
              : MessageManager.formatMessage("label.amend_delete_features",
-                     new String[] { sequences[0].getName() });
+                     new String[] { sequences.get(0).getName() });
  
+     /*
+      * show the dialog
+      */
      int reply = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
-             bigPanel, title, JvOptionPane.YES_NO_CANCEL_OPTION,
+             mainPanel, title, JvOptionPane.YES_NO_CANCEL_OPTION,
              JvOptionPane.QUESTION_MESSAGE, null, options,
              MessageManager.getString("action.ok"));
  
-     jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
+     FeaturesFile ffile = new FeaturesFile();
  
      if (reply == JvOptionPane.OK_OPTION && name.getText().length() > 0)
      {
        }
      }
  
-     if (!newFeatures)
+     if (!create)
      {
-       SequenceFeature sf = features[featureIndex];
+       SequenceFeature sf = features.get(featureIndex);
  
        if (reply == JvOptionPane.NO_OPTION)
        {
-         sequences[0].getDatasetSequence().deleteFeature(sf);
+         /*
+          * NO_OPTION corresponds to the Delete button
+          */
+         sequences.get(0).getDatasetSequence().deleteFeature(sf);
        }
        else if (reply == JvOptionPane.YES_OPTION)
        {
+         /*
+          * YES_OPTION corresponds to the Amend button
+          */
+         boolean typeChanged = !lastFeatureAdded.equals(sf.type);
 -        sf.type = lastFeatureAdded;
 -        sf.featureGroup = lastFeatureGroupAdded;
 -        sf.description = lastDescriptionAdded;
 -
 -        setColour(sf.type, fcol);
 -        getFeaturesDisplayed().setVisible(sf.type);
 -
 +        String newType = lastFeatureAdded;
 +        String newFeatureGroup = lastFeatureGroupAdded;
 +        String newDescription = lastDescriptionAdded;
 +
 +        setColour(newType, fcol);
 +        getFeaturesDisplayed().setVisible(newType);
 +        int newBegin = sf.begin;
 +        int newEnd = sf.end;
          try
          {
 -          sf.begin = ((Integer) start.getValue()).intValue();
 -          sf.end = ((Integer) end.getValue()).intValue();
 +          newBegin = ((Integer) start.getValue()).intValue();
 +          newEnd = ((Integer) end.getValue()).intValue();
          } catch (NumberFormatException ex)
          {
 +          // JSpinner doesn't accept invalid format data :-)
 +        }
 +
 +        /*
 +         * replace the feature by deleting it and adding a new one
 +         * (to ensure integrity of SequenceFeatures data store)
 +         */
-         sequences[0].deleteFeature(sf);
++        sequences.get(0).deleteFeature(sf);
 +        SequenceFeature newSf = new SequenceFeature(newType,
 +                newDescription, newBegin, newEnd, sf.getScore(),
 +                newFeatureGroup);
 +        // ensure any additional properties are copied
 +        if (sf.otherDetails != null)
 +        {
 +          newSf.otherDetails = new HashMap<String, Object>(sf.otherDetails);
 +        }
 +        ffile.parseDescriptionHTML(newSf, false);
 +        // add any additional links not parsed from description
 +        if (sf.links != null)
 +        {
 +          for (String link : sf.links)
 +          {
 +            newSf.addLink(link);
 +          }
          }
 +        // amend features only gets one sequence to act on
-         sequences[0].addSequenceFeature(newSf);
++        sequences.get(0).addSequenceFeature(newSf);
 -        ffile.parseDescriptionHTML(sf, false);
+         if (typeChanged)
+         {
+           findAllFeatures();
+         }
        }
      }
      else
      {
        if (reply == JvOptionPane.OK_OPTION && lastFeatureAdded.length() > 0)
        {
-         for (int i = 0; i < sequences.length; i++)
+         for (int i = 0; i < sequences.size(); i++)
          {
-           features[i].type = lastFeatureAdded;
+           SequenceFeature sf = features.get(i);
+           sf.type = lastFeatureAdded;
            // fix for JAL-1538 - always set feature group here
-           features[i].featureGroup = lastFeatureGroupAdded;
-           features[i].description = lastDescriptionAdded;
-           sequences[i].addSequenceFeature(features[i]);
-           ffile.parseDescriptionHTML(features[i], false);
+           sf.featureGroup = lastFeatureGroupAdded;
+           sf.description = lastDescriptionAdded;
+           sequences.get(i).addSequenceFeature(sf);
+           ffile.parseDescriptionHTML(sf, false);
          }
  
          if (lastFeatureGroupAdded != null)
  
          findAllFeatures(false);
  
-         ap.paintAlignment(true);
+         alignPanel.paintAlignment(true);
  
          return true;
        }
        }
      }
  
-     ap.paintAlignment(true);
+     alignPanel.paintAlignment(true);
  
      return true;
    }