refactored do and undo() method to take array of alignments for operations that resul...
[jalview.git] / src / jalview / commands / EditCommand.java
index cbcc700..aece057 100644 (file)
@@ -73,7 +73,7 @@ public class EditCommand
           new Edit(command, seqs, position, number, al)};
     }
 
-    performEdit(0);
+    performEdit(0, null);
   }
 
   public EditCommand(String description,
@@ -91,7 +91,7 @@ public class EditCommand
           { new Edit(command, seqs, position, number, al, replace)};
     }
 
-    performEdit(0);
+    performEdit(0, null);
   }
 
   final public String getDescription()
@@ -109,12 +109,42 @@ public class EditCommand
     return edits[0].al;
   }
 
+  /**
+   * append a new editCommand
+   * Note. this shouldn't be called if the edit is an operation affects more alignment objects than the one referenced
+   * in al (for example, cut or pasting whole sequences). Use the form with an additional AlignmentI[] views parameter. 
+   * @param command
+   * @param seqs
+   * @param position
+   * @param number
+   * @param al
+   * @param performEdit
+   */
+  final public void appendEdit(int command,
+          SequenceI[] seqs,
+          int position,
+          int number,
+          AlignmentI al,
+          boolean performEdit)
+  {
+    appendEdit(command, seqs, position, number, al, performEdit, null);
+  }
+  /**
+   * append a new edit command with a set of alignment views that may be operated on
+   * @param command
+   * @param seqs
+   * @param position
+   * @param number
+   * @param al
+   * @param performEdit
+   * @param views
+   */
   final public void appendEdit(int command,
                                SequenceI[] seqs,
                                int position,
                                int number,
                                AlignmentI al,
-                               boolean performEdit)
+                               boolean performEdit, AlignmentI[] views)
   {
     Edit edit = new Edit(command, seqs, position, number, al.getGapCharacter());
     if (al.getHeight() == seqs.length)
@@ -139,11 +169,11 @@ public class EditCommand
 
     if (performEdit)
     {
-      performEdit(edits.length - 1);
+      performEdit(edits.length - 1, views);
     }
   }
 
-  final void performEdit(int commandIndex)
+  final void performEdit(int commandIndex, AlignmentI[] views)
   {
     int eSize = edits.length;
     for (int e = commandIndex; e < eSize; e++)
@@ -157,10 +187,10 @@ public class EditCommand
         deleteGap(edits[e]);
           break;
         case CUT:
-        cut(edits[e]);
+        cut(edits[e], views);
           break;
         case PASTE:
-        paste(edits[e]);
+        paste(edits[e], views);
           break;
         case REPLACE:
           replace(edits[e]);
@@ -169,12 +199,12 @@ public class EditCommand
     }
   }
 
-  final public void doCommand()
+  final public void doCommand(AlignmentI[] views)
   {
-    performEdit(0);
+    performEdit(0,views);
   }
 
-  final public void undoCommand()
+  final public void undoCommand(AlignmentI[] views)
   {
     int e = 0, eSize = edits.length;
     for (e = eSize - 1; e > -1; e--)
@@ -188,10 +218,10 @@ public class EditCommand
         insertGap(edits[e]);
           break;
         case CUT:
-        paste(edits[e]);
+        paste(edits[e], views);
           break;
         case PASTE:
-        cut(edits[e]);
+        cut(edits[e], views);
           break;
         case REPLACE:
           replace(edits[e]);
@@ -209,7 +239,7 @@ public class EditCommand
                                    command.gapChar);
     }
 
-    adjustAnnotations(command, true, false);
+    adjustAnnotations(command, true, false, null);
   }
 
   final void deleteGap(Edit command)
@@ -220,10 +250,10 @@ public class EditCommand
                                   command.position + command.number);
     }
 
-    adjustAnnotations(command, false, false);
+    adjustAnnotations(command, false, false, null);
   }
 
-  void cut(Edit command)
+  void cut(Edit command, AlignmentI[] views)
   {
     boolean seqDeleted=false;
     command.string = new char[command.seqs.length][];
@@ -264,10 +294,10 @@ public class EditCommand
       }
     }
 
-    adjustAnnotations(command, false, seqDeleted);
+    adjustAnnotations(command, false, seqDeleted, views);
   }
 
-  void paste(Edit command)
+  void paste(Edit command, AlignmentI[] views)
   {
     StringBuffer tmp;
     boolean newDSNeeded;
@@ -345,7 +375,7 @@ public class EditCommand
         adjustFeatures(command, i, start, end, true);
       }
     }
-    adjustAnnotations(command, true, seqWasDeleted);
+    adjustAnnotations(command, true, seqWasDeleted, views);
 
     command.string = null;
   }
@@ -371,7 +401,7 @@ public class EditCommand
     }
   }
 
-  final void adjustAnnotations(Edit command, boolean insert, boolean modifyVisibility)
+  final void adjustAnnotations(Edit command, boolean insert, boolean modifyVisibility, AlignmentI[] views)
   {
 
     AlignmentAnnotation[] annotations = null;
@@ -398,12 +428,55 @@ public class EditCommand
             // remove rows
             tmp = command.seqs[s].getAnnotation();
             if (tmp!=null) {
-              command.deletedAnnotationRows.put(command.seqs[s], tmp);
+              int alen=tmp.length;
               for (int aa =0; aa<tmp.length; aa++)
               {
-                command.al.deleteAnnotation(tmp[aa]);
+                if (!command.al.deleteAnnotation(tmp[aa]))
+                {
+                  // strip out annotation not in the current al (will be put back on insert in all views)
+                  tmp[aa] = null;
+                  alen--;
+                }
               }
               command.seqs[s].setAlignmentAnnotation(null);
+              if (alen!=tmp.length)
+              { 
+                // save the non-null annotation references only
+                AlignmentAnnotation[] saved = new AlignmentAnnotation[alen];
+                for (int aa=0,aapos=0;aa<tmp.length;aa++)
+                {
+                  if (tmp[aa]!=null)
+                  {
+                    saved[aapos++] = tmp[aa];
+                    tmp[aa] = null;
+                  }
+                }
+                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++)
+                {
+                  if (views[alview]!=command.al)
+                  {
+                    AlignmentAnnotation[] toremove = views[alview].getAlignmentAnnotation();
+                    if (toremove==null || toremove.length==0)
+                    {
+                      continue;
+                    }
+                    // remove any alignment annotation on this sequence that's on that alignment view.
+                    for (int aa = 0; aa<toremove.length; aa++)
+                    {
+                      if (toremove[aa].sequenceRef==command.seqs[s])
+                      {
+                        views[alview].deleteAnnotation(toremove[aa]);
+                      }
+                    }
+                  }
+                }
+              } else {
+                // save all the annotation
+                command.deletedAnnotationRows.put(command.seqs[s], tmp);
+              }
             }
           } else {
             // recover rows
@@ -414,12 +487,30 @@ public class EditCommand
               if (revealed!=null) {
                 for (int aa =0; aa<revealed.length; aa++)
                 {
+                  // iterate through al adding original annotation
                   command.al.addAnnotation(revealed[aa]);
                 }
                 for (int aa =0; aa<revealed.length; aa++)
                 {
                   command.al.setAnnotationIndex(revealed[aa], aa);
                 }
+                // and then duplicate added annotation on every other alignment view
+                for (int vnum=0; views!=null && vnum<views.length; vnum++)
+                {
+                  if (views[vnum]!=command.al)
+                  {
+                    int avwidth = views[vnum].getWidth()+1;
+                    // duplicate in this view
+                    for (int a=0; a<revealed.length; a++)
+                    {
+                      AlignmentAnnotation newann = new AlignmentAnnotation(revealed[a]);
+                      command.seqs[s].addAlignmentAnnotation(newann);
+                      newann.padAnnotation(avwidth);
+                      views[vnum].addAnnotation(newann);
+                      views[vnum].setAnnotationIndex(newann, a);
+                    }
+                  }
+                }
               }
             }
           }