JAL-2822 stash start/end before setSequence (which will modify ‘end’) and catch cases...
[jalview.git] / src / jalview / commands / EditCommand.java
index 334f30d..894dc75 100644 (file)
@@ -536,8 +536,21 @@ public class EditCommand implements CommandI
         boolean cutIsInternal = cutPositions != null
                 && sequence.getStart() != cutPositions
                 .getBegin() && sequence.getEnd() != cutPositions.getEnd();
+
+        /*
+         * perform the cut; if this results in a new dataset sequence, add
+         * that to the alignment dataset
+         */
+        SequenceI ds = sequence.getDatasetSequence();
         sequence.deleteChars(command.position, command.position
                 + command.number);
+        SequenceI newDs = sequence.getDatasetSequence();
+        if (newDs != ds && command.al != null
+                && command.al.getDataset() != null
+                && !command.al.getDataset().getSequences().contains(newDs))
+        {
+          command.al.getDataset().addSequence(newDs);
+        }
 
         if (command.oldds != null && command.oldds[i] != null)
         {
@@ -556,12 +569,13 @@ public class EditCommand implements CommandI
           {
             command.oldds = new SequenceI[command.seqs.length];
           }
-          command.oldds[i] = oldds;
+          command.oldds[i] = oldds;// todo not if !cutIsInternal?
 
           // do we need to edit sequence features for new sequence ?
           if (oldds != sequence.getDatasetSequence()
                   || (cutIsInternal
                           && sequence.getFeatures().hasFeatures()))
+          // todo or just test cutIsInternal && cutPositions != null ?
           {
             if (cutPositions != null)
             {
@@ -762,6 +776,10 @@ public class EditCommand implements CommandI
       {
         tmp.append(oldstring.substring(end));
       }
+      // stash end prior to updating the sequence object so we can save it if
+      // need be.
+      Range oldstartend = new Range(command.seqs[i].getStart(),
+              command.seqs[i].getEnd());
       command.seqs[i].setSequence(tmp.toString());
       command.string[i] = oldstring
               .substring(start, Math.min(end, oldstring.length()))
@@ -771,30 +789,32 @@ public class EditCommand implements CommandI
 
       if (!nogaprep.toLowerCase().equals(nogapold.toLowerCase()))
       {
-        // probably need a new dataset sequence
-        if (newDSWasNeeded)
+        // we may already have dataset and limits stashed...
+        if (newDSWasNeeded || newStartEndWasNeeded)
         {
+          if (newDSWasNeeded)
+          {
           // then just switch the dataset sequence
           SequenceI oldds = command.seqs[i].getDatasetSequence();
           command.seqs[i].setDatasetSequence(command.oldds[i]);
           command.oldds[i] = oldds;
-        }
-        else
-        if (newStartEndWasNeeded)
-        {
-          Range newStart = command.oldStartEnd[i];
-          command.oldStartEnd[i] = new Range(command.seqs[i].getStart(),
-                  command.seqs[i].getEnd());
-          command.seqs[i].setStart(newStart.getBegin());
-          command.seqs[i].setEnd(newStart.getEnd());
+          }
+          if (newStartEndWasNeeded)
+          {
+            Range newStart = command.oldStartEnd[i];
+            command.oldStartEnd[i] = oldstartend;
+            command.seqs[i].setStart(newStart.getBegin());
+            command.seqs[i].setEnd(newStart.getEnd());
+          }
         }
         else         
         {
+          // decide if we need a new dataset sequence or modify start/end
           // first edit the original dataset sequence string
           SequenceI oldds = command.seqs[i].getDatasetSequence();
-          String fullseq, osp = oldds.getSequenceAsString();
+          String osp = oldds.getSequenceAsString();
 
-          fullseq = osp.substring(0, ipos) + nogaprep
+          String fullseq = osp.substring(0, ipos) + nogaprep
                   + osp.substring(ipos + nogaprep.length());
 
           // and check if new sequence data is different..
@@ -832,7 +852,8 @@ public class EditCommand implements CommandI
             {
               // modification at end
               command.seqs[i].setEnd(
-                      beforeEditedPositions.getEnd() + nogaprep.length());
+                      beforeEditedPositions.getEnd() + nogaprep.length()
+                              - nogapold.length());
             }
             else if (afterEditedPositions != null
                     && beforeEditedPositions == null)
@@ -1401,43 +1422,45 @@ public class EditCommand implements CommandI
 
   public class Edit
   {
-    public SequenceI[] oldds;
+    private SequenceI[] oldds;
 
     /**
      * start and end of sequence prior to edit
      */
-    public Range[] oldStartEnd;
+    private Range[] oldStartEnd;
 
-    boolean fullAlignmentHeight = false;
+    private boolean fullAlignmentHeight = false;
 
-    Map<SequenceI, AlignmentAnnotation[]> deletedAnnotationRows;
+    private Map<SequenceI, AlignmentAnnotation[]> deletedAnnotationRows;
 
-    Map<String, Annotation[]> deletedAnnotations;
+    private Map<String, Annotation[]> deletedAnnotations;
 
     /*
      * features deleted by the cut (re-add on Undo)
      * (including the original of any shortened features)
      */
-    Map<SequenceI, List<SequenceFeature>> deletedFeatures;
+    private Map<SequenceI, List<SequenceFeature>> deletedFeatures;
 
     /*
      * shortened features added by the cut (delete on Undo)
      */
-    Map<SequenceI, List<SequenceFeature>> truncatedFeatures;
+    private Map<SequenceI, List<SequenceFeature>> truncatedFeatures;
 
-    AlignmentI al;
+    private AlignmentI al;
 
-    Action command;
+    final private Action command;
 
     char[][] string;
 
     SequenceI[] seqs;
 
-    int[] alIndex;
+    private int[] alIndex;
+
+    private int position;
 
-    int position, number;
+    private int number;
 
-    char gapChar;
+    private char gapChar;
 
     public Edit(Action cmd, SequenceI[] sqs, int pos, int count,
             char gap)
@@ -1465,6 +1488,16 @@ public class EditCommand implements CommandI
       fullAlignmentHeight = (align.getHeight() == sqs.length);
     }
 
+    /**
+     * Constructor given a REPLACE command and the replacement string
+     * 
+     * @param cmd
+     * @param sqs
+     * @param pos
+     * @param count
+     * @param align
+     * @param replace
+     */
     Edit(Action cmd, SequenceI[] sqs, int pos, int count,
             AlignmentI align, String replace)
     {
@@ -1529,7 +1562,7 @@ public class EditCommand implements CommandI
    * <li>features right of the cut are shifted left</li>
    * <li>features internal to the cut region are deleted</li>
    * <li>features that overlap or span the cut are shortened</li>
-   * <li>the originals of any deleted or shorted features are saved, to re-add
+   * <li>the originals of any deleted or shortened features are saved, to re-add
    * on Undo</li>
    * <li>any added (shortened) features are saved, to delete on Undo</li>
    * </ul>
@@ -1543,8 +1576,9 @@ public class EditCommand implements CommandI
   protected static void cutFeatures(Edit command, SequenceI seq,
           int fromPosition, int toPosition, boolean cutIsInternal)
   {
-    /* if the cut is at start or end of sequence
-     * then we don't modify the seuqence feature store
+    /* 
+     * if the cut is at start or end of sequence
+     * then we don't modify the sequence feature store
      */
     if (!cutIsInternal)
     {