new Edit(command, seqs, position, number, al)};
}
- performEdit(0);
+ performEdit(0, null);
}
public EditCommand(String description,
{ new Edit(command, seqs, position, number, al, replace)};
}
- performEdit(0);
+ performEdit(0, null);
}
final public String getDescription()
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)
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++)
switch(edits[e].command)
{
case INSERT_GAP:
- insertGap(edits[e]);
+ insertGap(edits[e]);
break;
case DELETE_GAP:
- deleteGap(edits[e]);
+ 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]);
}
}
- 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--)
switch (edits[e].command)
{
case INSERT_GAP:
- deleteGap(edits[e]);
+ deleteGap(edits[e]);
break;
case DELETE_GAP:
- insertGap(edits[e]);
+ 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]);
final void insertGap(Edit command)
{
+
for (int s = 0; s < command.seqs.length; s++)
{
command.seqs[s].insertCharAt(command.position,
command.gapChar);
}
- adjustAnnotations(command, true, false);
+ adjustAnnotations(command, true, false, null);
}
final void deleteGap(Edit command)
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][];
{
command.string[i] = command.seqs[i].getSequence(command.position,
command.position + command.number);
-
- if (command.seqs[i].getDatasetSequence() != null
- || command.seqs[i].getSequenceFeatures() != null)
+ SequenceI oldds = command.seqs[i].getDatasetSequence();
+ if (command.oldds!=null && command.oldds[i]!=null)
{
- for (int s = command.position; s < command.position + command.number;
- s++)
+ // we are redoing an undone cut.
+ command.seqs[i].setDatasetSequence(null);
+ }
+ command.seqs[i].deleteChars(command.position,
+ command.position + command.number);
+ if (command.oldds!=null && command.oldds[i]!=null)
+ {
+ // oldds entry contains the cut dataset sequence.
+ command.seqs[i].setDatasetSequence(command.oldds[i]);
+ command.oldds[i] = oldds;
+ } else {
+ // modify the oldds if necessary
+ if (oldds!=command.seqs[i].getDatasetSequence()
+ || command.seqs[i].getSequenceFeatures() != null)
{
- if (jalview.schemes.ResidueProperties
- .aaIndex[command.seqs[i].getCharAt(s)] != 23)
+ if (command.oldds==null)
{
- adjustFeatures(command, i,
- command.seqs[i].findPosition(command.position),
- command.seqs[i].findPosition(command.position +
- command.number),
- false);
- break;
+ command.oldds = new SequenceI[command.seqs.length];
}
+ command.oldds[i] = oldds;
+ adjustFeatures(command, i,
+ command.seqs[i].findPosition(command.position),
+ command.seqs[i].findPosition(command.position +
+ command.number),
+ false);
}
}
- command.seqs[i].deleteChars(command.position,
- command.position + command.number);
}
if (command.seqs[i].getLength() < 1)
}
}
- adjustAnnotations(command, false, seqDeleted);
+ adjustAnnotations(command, false, seqDeleted, views);
}
- void paste(Edit command)
+ void paste(Edit command, AlignmentI[] views)
{
StringBuffer tmp;
boolean newDSNeeded;
+ boolean newDSWasNeeded;
+ int newstart,newend;
boolean seqWasDeleted=false;
int start = 0, end = 0;
for (int i = 0; i < command.seqs.length; i++)
{
newDSNeeded = false;
+ newDSWasNeeded = command.oldds!=null && command.oldds[i]!=null;
if (command.seqs[i].getLength() < 1)
{
// ie this sequence was deleted, we need to
}
seqWasDeleted=true;
}
+ newstart = command.seqs[i].getStart();
+ newend = command.seqs[i].getEnd();
+
tmp = new StringBuffer();
tmp.append(command.seqs[i].getSequence());
-
+ //Undo of a delete does not replace original dataset sequence on to alignment sequence.
+
if (command.string != null && command.string[i] != null)
{
if (command.position >= tmp.length())
}
}
tmp.insert(command.position, command.string[i]);
-
for (int s = 0; s < command.string[i].length; s++)
{
if (jalview.schemes.ResidueProperties.aaIndex[command.string[i][s]] !=
23)
{
- newDSNeeded = true;
- start = command.seqs[i].findPosition(command.position);
- end = command.seqs[i].findPosition(command.position +
+ if (!newDSNeeded)
+ {
+ newDSNeeded = true;
+ start = command.seqs[i].findPosition(command.position);
+ end = command.seqs[i].findPosition(command.position +
command.number);
- break;
+ }
+ if (command.seqs[i].getStart()==start)
+ newstart--;
+ else
+ newend++;
}
}
command.string[i] = null;
}
command.seqs[i].setSequence(tmp.toString());
-
+ command.seqs[i].setStart(newstart);
+ command.seqs[i].setEnd(newend);
if (newDSNeeded)
{
if (command.seqs[i].getDatasetSequence() != null)
- { // use new ds mechanism here
- Sequence ds = new Sequence(command.seqs[i].getName(),
+ {
+ SequenceI ds;
+ if (newDSWasNeeded)
+ {
+ ds = command.oldds[i];
+ } else {
+ // make a new DS sequence
+ // use new ds mechanism here
+ ds= new Sequence(command.seqs[i].getName(),
jalview.analysis.AlignSeq.extractGaps(
jalview.util.Comparison.GapChars,
command.seqs[i].getSequenceAsString()
),
command.seqs[i].getStart(),
command.seqs[i].getEnd());
- ds.setDescription(command.seqs[i].getDescription());
+ ds.setDescription(command.seqs[i].getDescription());
+ }
+ if (command.oldds==null)
+ {
+ command.oldds = new SequenceI[command.seqs.length];
+ }
+ command.oldds[i]=command.seqs[i].getDatasetSequence();
command.seqs[i].setDatasetSequence(ds);
}
-
adjustFeatures(command, i, start, end, true);
}
}
- adjustAnnotations(command, true, seqWasDeleted);
+ adjustAnnotations(command, true, seqWasDeleted, views);
command.string = null;
}
}
}
- final void adjustAnnotations(Edit command, boolean insert, boolean modifyVisibility)
+ final void adjustAnnotations(Edit command, boolean insert, boolean modifyVisibility, AlignmentI[] views)
{
AlignmentAnnotation[] annotations = null;
// 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
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);
+ }
+ }
+ }
}
}
}
Annotation[] temp;
for (int a = 0; a < annotations.length; a++)
{
- if (annotations[a].autoCalculated)
+ if (annotations[a].autoCalculated || annotations[a].annotations == null)
{
continue;
}
for (int aa = 0; aa < temp.length; aa++)
{
temp[aa] = new Annotation(
- command.al.getGapCharacter()+"",
+ command.gapChar+"",
null, ' ', 0);
}
}
{
if (command.position < aSize)
{
- if (command.position + command.number > aSize)
+ if (command.position + command.number >= aSize)
{
tSize = aSize;
}
else
{
- tSize = aSize - command.number + command.position;
+ tSize = aSize - command.number;
}
}
else
tSize = aSize;
}
temp = new Annotation[tSize];
-
}
+
if (insert)
{
if (command.position < annotations[a].annotations.length)
0, temp, 0, copylen); //command.position);
Annotation[] deleted = new Annotation[command.number];
- if (copylen>command.position) {
+ if (copylen>=command.position) {
copylen = Math.min(command.number, annotations[a].annotations.length-command.position);
if (copylen>0)
{
class Edit
{
+ public SequenceI[] oldds;
boolean fullAlignmentHeight = false;
Hashtable deletedAnnotationRows;
Hashtable deletedAnnotations;
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++)
{
fullAlignmentHeight = (al.getHeight() == seqs.length);
}
}
-
}