Merge branch 'develop' into features/JAL-2446NCList
[jalview.git] / src / jalview / commands / EditCommand.java
index 21ff841..cac843f 100644 (file)
@@ -122,15 +122,15 @@ public class EditCommand implements CommandI
   {
   }
 
-  public EditCommand(String description)
+  public EditCommand(String desc)
   {
-    this.description = description;
+    this.description = desc;
   }
 
-  public EditCommand(String description, Action command, SequenceI[] seqs,
+  public EditCommand(String desc, Action command, SequenceI[] seqs,
           int position, int number, AlignmentI al)
   {
-    this.description = description;
+    this.description = desc;
     if (command == Action.CUT || command == Action.PASTE)
     {
       setEdit(new Edit(command, seqs, position, number, al));
@@ -139,10 +139,10 @@ public class EditCommand implements CommandI
     performEdit(0, null);
   }
 
-  public EditCommand(String description, Action command, String replace,
+  public EditCommand(String desc, Action command, String replace,
           SequenceI[] seqs, int position, int number, AlignmentI al)
   {
-    this.description = description;
+    this.description = desc;
     if (command == Action.REPLACE)
     {
       setEdit(new Edit(command, seqs, position, number, al, replace));
@@ -222,14 +222,16 @@ public class EditCommand implements CommandI
     /**
      * Check a contiguous edit; either
      * <ul>
-     * <li>a new Insert <n> positions to the right of the last <insert n>, or</li>
+     * <li>a new Insert <n> positions to the right of the last <insert n>,
+     * or</li>
      * <li>a new Delete <n> gaps which is <n> positions to the left of the last
      * delete.</li>
      * </ul>
      */
-    boolean contiguous = (action == Action.INSERT_GAP && e.position == lastEdit.position
-            + lastEdit.number)
-            || (action == Action.DELETE_GAP && e.position + e.number == lastEdit.position);
+    boolean contiguous = (action == Action.INSERT_GAP
+            && e.position == lastEdit.position + lastEdit.number)
+            || (action == Action.DELETE_GAP
+                    && e.position + e.number == lastEdit.position);
     if (contiguous)
     {
       /*
@@ -475,7 +477,8 @@ public class EditCommand implements CommandI
     {
       command.seqs[s].insertCharAt(command.position, command.number,
               command.gapChar);
-      // System.out.println("pos: "+command.position+" number: "+command.number);
+      // System.out.println("pos: "+command.position+" number:
+      // "+command.number);
     }
 
     adjustAnnotations(command, true, false, null);
@@ -504,8 +507,8 @@ public class EditCommand implements CommandI
   {
     for (int s = 0; s < command.seqs.length; s++)
     {
-      command.seqs[s].deleteChars(command.position, command.position
-              + command.number);
+      command.seqs[s].deleteChars(command.position,
+              command.position + command.number);
     }
 
     adjustAnnotations(command, false, false, null);
@@ -536,8 +539,8 @@ public class EditCommand implements CommandI
           // we are redoing an undone cut.
           sequence.setDatasetSequence(null);
         }
-        sequence.deleteChars(command.position, command.position
-                + command.number);
+        sequence.deleteChars(command.position,
+                command.position + command.number);
         if (command.oldds != null && command.oldds[i] != null)
         {
           // oldds entry contains the cut dataset sequence.
@@ -548,13 +551,14 @@ public class EditCommand implements CommandI
         {
           // modify the oldds if necessary
           if (oldds != sequence.getDatasetSequence()
-                  || sequence.getSequenceFeatures() != null)
+                  || sequence.getFeatures().hasFeatures())
           {
             if (command.oldds == null)
             {
               command.oldds = new SequenceI[command.seqs.length];
             }
             command.oldds[i] = oldds;
+            // FIXME JAL-2541 JAL-2526 get correct positions if on a gap
             adjustFeatures(
                     command,
                     i,
@@ -646,8 +650,8 @@ public class EditCommand implements CommandI
             {
               newDSNeeded = true;
               start = command.seqs[i].findPosition(command.position);
-              end = command.seqs[i].findPosition(command.position
-                      + command.number);
+              end = command.seqs[i]
+                      .findPosition(command.position + command.number);
             }
             if (command.seqs[i].getStart() == start)
             {
@@ -731,16 +735,16 @@ public class EditCommand implements CommandI
       tmp = new StringBuffer(oldstring.substring(0, start));
       tmp.append(command.string[i]);
       String nogaprep = jalview.analysis.AlignSeq.extractGaps(
-              jalview.util.Comparison.GapChars, new String(
-                      command.string[i]));
+              jalview.util.Comparison.GapChars,
+              new String(command.string[i]));
       int ipos = command.seqs[i].findPosition(start)
               - command.seqs[i].getStart();
       tmp.append(oldstring.substring(end));
       command.seqs[i].setSequence(tmp.toString());
       command.string[i] = oldstring.substring(start, end).toCharArray();
       String nogapold = jalview.analysis.AlignSeq.extractGaps(
-              jalview.util.Comparison.GapChars, new String(
-                      command.string[i]));
+              jalview.util.Comparison.GapChars,
+              new String(command.string[i]));
       if (!nogaprep.toLowerCase().equals(nogapold.toLowerCase()))
       {
         if (newDSWasNeeded)
@@ -797,6 +801,8 @@ public class EditCommand implements CommandI
       AlignmentAnnotation[] tmp;
       for (int s = 0; s < command.seqs.length; s++)
       {
+        command.seqs[s].sequenceChanged();
+
         if (modifyVisibility)
         {
           // Rows are only removed or added to sequence object.
@@ -833,7 +839,8 @@ public class EditCommand implements CommandI
                 tmp = saved;
                 command.deletedAnnotationRows.put(command.seqs[s], saved);
                 // and then remove any annotation in the other views
-                for (int alview = 0; views != null && alview < views.length; alview++)
+                for (int alview = 0; views != null
+                        && alview < views.length; alview++)
                 {
                   if (views[alview] != command.al)
                   {
@@ -885,7 +892,8 @@ public class EditCommand implements CommandI
                 }
                 // and then duplicate added annotation on every other alignment
                 // view
-                for (int vnum = 0; views != null && vnum < views.length; vnum++)
+                for (int vnum = 0; views != null
+                        && vnum < views.length; vnum++)
                 {
                   if (views[vnum] != command.al)
                   {
@@ -1012,8 +1020,8 @@ public class EditCommand implements CommandI
           }
 
           System.arraycopy(annotations[a].annotations, command.position,
-                  temp, command.position + command.number, aSize
-                          - command.position);
+                  temp, command.position + command.number,
+                  aSize - command.position);
         }
         else
         {
@@ -1056,8 +1064,8 @@ public class EditCommand implements CommandI
                     annotations[a].annotations.length - command.position);
             if (copylen > 0)
             {
-              System.arraycopy(annotations[a].annotations,
-                      command.position, deleted, 0, copylen); // command.number);
+              System.arraycopy(annotations[a].annotations, command.position,
+                      deleted, 0, copylen); // command.number);
             }
           }
 
@@ -1066,10 +1074,10 @@ public class EditCommand implements CommandI
           if (annotations[a].annotations.length > command.position
                   + command.number)
           {
-            System.arraycopy(annotations[a].annotations, command.position
-                    + command.number, temp, command.position,
-                    annotations[a].annotations.length - command.position
-                            - command.number); // aSize
+            System.arraycopy(annotations[a].annotations,
+                    command.position + command.number, temp,
+                    command.position, annotations[a].annotations.length
+                            - command.position - command.number); // aSize
           }
         }
         else
@@ -1101,8 +1109,8 @@ public class EditCommand implements CommandI
     }
   }
 
-  final static void adjustFeatures(Edit command, int index, int i, int j,
-          boolean insert)
+  final static void adjustFeatures(Edit command, int index, final int i,
+          final int j, boolean insert)
   {
     SequenceI seq = command.seqs[index];
     SequenceI sequence = seq.getDatasetSequence();
@@ -1122,56 +1130,73 @@ public class EditCommand implements CommandI
       return;
     }
 
-    SequenceFeature[] sf = sequence.getSequenceFeatures();
+    List<SequenceFeature> sf = sequence.getFeatures()
+            .getPositionalFeatures();
 
-    if (sf == null)
+    if (sf.isEmpty())
     {
       return;
     }
 
-    SequenceFeature[] oldsf = new SequenceFeature[sf.length];
+    List<SequenceFeature> oldsf = new ArrayList<SequenceFeature>();
 
     int cSize = j - i;
 
-    for (int s = 0; s < sf.length; s++)
+    for (SequenceFeature feature : sf)
     {
-      SequenceFeature copy = new SequenceFeature(sf[s]);
+      SequenceFeature copy = new SequenceFeature(feature);
 
-      oldsf[s] = copy;
+      oldsf.add(copy);
 
-      if (sf[s].getEnd() < i)
+      if (feature.getEnd() < i)
       {
         continue;
       }
 
-      if (sf[s].getBegin() > j)
+      if (feature.getBegin() > j)
       {
-        sf[s].setBegin(copy.getBegin() - cSize);
-        sf[s].setEnd(copy.getEnd() - cSize);
+        int newBegin = copy.getBegin() - cSize;
+        int newEnd = copy.getEnd() - cSize;
+        SequenceFeature newSf = new SequenceFeature(feature, newBegin,
+                newEnd, feature.getFeatureGroup(), feature.getScore());
+        sequence.deleteFeature(feature);
+        sequence.addSequenceFeature(newSf);
+        // feature.setBegin(newBegin);
+        // feature.setEnd(newEnd);
         continue;
       }
 
-      if (sf[s].getBegin() >= i)
+      int newBegin = feature.getBegin();
+      int newEnd = feature.getEnd();
+      if (newBegin >= i)
       {
-        sf[s].setBegin(i);
+        newBegin = i;
+        // feature.setBegin(i);
       }
 
-      if (sf[s].getEnd() < j)
+      if (newEnd < j)
       {
-        sf[s].setEnd(j - 1);
+        newEnd = j - 1;
+        // feature.setEnd(j - 1);
       }
+      newEnd = newEnd - cSize;
+      // feature.setEnd(feature.getEnd() - (cSize));
 
-      sf[s].setEnd(sf[s].getEnd() - (cSize));
-
-      if (sf[s].getBegin() > sf[s].getEnd())
+      sequence.deleteFeature(feature);
+      if (newEnd >= newBegin)
       {
-        sequence.deleteFeature(sf[s]);
+        sequence.addSequenceFeature(new SequenceFeature(feature, newBegin,
+                newEnd, feature.getFeatureGroup(), feature.getScore()));
       }
+      // if (feature.getBegin() > feature.getEnd())
+      // {
+      // sequence.deleteFeature(feature);
+      // }
     }
 
     if (command.editedFeatures == null)
     {
-      command.editedFeatures = new Hashtable<SequenceI, SequenceFeature[]>();
+      command.editedFeatures = new Hashtable<SequenceI, List<SequenceFeature>>();
     }
 
     command.editedFeatures.put(seq, oldsf);
@@ -1298,7 +1323,7 @@ public class EditCommand implements CommandI
 
     Hashtable<String, Annotation[]> deletedAnnotations;
 
-    Hashtable<SequenceI, SequenceFeature[]> editedFeatures;
+    Hashtable<SequenceI, List<SequenceFeature>> editedFeatures;
 
     AlignmentI al;
 
@@ -1314,51 +1339,51 @@ public class EditCommand implements CommandI
 
     char gapChar;
 
-    public Edit(Action command, SequenceI[] seqs, int position, int number,
-            char gapChar)
+    public Edit(Action cmd, SequenceI[] sqs, int pos, int count,
+            char gap)
     {
-      this.command = command;
-      this.seqs = seqs;
-      this.position = position;
-      this.number = number;
-      this.gapChar = gapChar;
+      this.command = cmd;
+      this.seqs = sqs;
+      this.position = pos;
+      this.number = count;
+      this.gapChar = gap;
     }
 
-    Edit(Action command, SequenceI[] seqs, int position, int number,
-            AlignmentI al)
+    Edit(Action cmd, SequenceI[] sqs, int pos, int count,
+            AlignmentI align)
     {
-      this.gapChar = al.getGapCharacter();
-      this.command = command;
-      this.seqs = seqs;
-      this.position = position;
-      this.number = number;
-      this.al = al;
-
-      alIndex = new int[seqs.length];
-      for (int i = 0; i < seqs.length; i++)
+      this.gapChar = align.getGapCharacter();
+      this.command = cmd;
+      this.seqs = sqs;
+      this.position = pos;
+      this.number = count;
+      this.al = align;
+
+      alIndex = new int[sqs.length];
+      for (int i = 0; i < sqs.length; i++)
       {
-        alIndex[i] = al.findIndex(seqs[i]);
+        alIndex[i] = align.findIndex(sqs[i]);
       }
 
-      fullAlignmentHeight = (al.getHeight() == seqs.length);
+      fullAlignmentHeight = (align.getHeight() == sqs.length);
     }
 
-    Edit(Action command, SequenceI[] seqs, int position, int number,
-            AlignmentI al, String replace)
+    Edit(Action cmd, SequenceI[] sqs, int pos, int count,
+            AlignmentI align, String replace)
     {
-      this.command = command;
-      this.seqs = seqs;
-      this.position = position;
-      this.number = number;
-      this.al = al;
-      this.gapChar = al.getGapCharacter();
-      string = new char[seqs.length][];
-      for (int i = 0; i < seqs.length; i++)
+      this.command = cmd;
+      this.seqs = sqs;
+      this.position = pos;
+      this.number = count;
+      this.al = align;
+      this.gapChar = align.getGapCharacter();
+      string = new char[sqs.length][];
+      for (int i = 0; i < sqs.length; i++)
       {
         string[i] = replace.toCharArray();
       }
 
-      fullAlignmentHeight = (al.getHeight() == seqs.length);
+      fullAlignmentHeight = (align.getHeight() == sqs.length);
     }
 
     public SequenceI[] getSequences()