command.oldds = new SequenceI[command.seqs.length];
}
command.oldds[i] = oldds;
+ if (oldds != sequence.getDatasetSequence())
+ {
+ oldds.getFeatures().deleteAll();
+ }
if (cutPositions != null)
{
*/
static 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;
+ boolean newDSNeeded = false;
+ boolean newDSWasNeeded = command.oldds != null
+ && command.oldds[i] != null;
SequenceI sequence = command.seqs[i];
if (sequence.getLength() < 1)
{
- // ie this sequence was deleted, we need to
- // readd it to the alignment
+ /*
+ * sequence was deleted; re-add it to the alignment
+ */
if (command.alIndex[i] < command.al.getHeight())
{
List<SequenceI> sequences;
}
seqWasDeleted = true;
}
- newstart = sequence.getStart();
- newend = sequence.getEnd();
+ int newStart = sequence.getStart();
+ int newEnd = sequence.getEnd();
- tmp = new StringBuffer();
+ StringBuilder tmp = new StringBuilder();
tmp.append(sequence.getSequence());
// Undo of a delete does not replace original dataset sequence on to
// alignment sequence.
+ int start = 0;
+ int length = 0;
+
if (command.string != null && command.string[i] != null)
{
if (command.position >= tmp.length())
{
// This occurs if padding is on, and residues
// are removed from end of alignment
- int length = command.position - tmp.length();
- while (length > 0)
+ int len = command.position - tmp.length();
+ while (len > 0)
{
tmp.append(command.gapChar);
- length--;
+ len--;
}
}
tmp.insert(command.position, command.string[i]);
{
if (!Comparison.isGap(command.string[i][s]))
{
+ length++;
if (!newDSNeeded)
{
newDSNeeded = true;
start = sequence.findPosition(command.position);
- end = sequence.findPosition(command.position
- + command.number);
+ // end = sequence
+ // .findPosition(command.position + command.number);
}
if (sequence.getStart() == start)
{
- newstart--;
+ newStart--;
}
else
{
- newend++;
+ newEnd++;
}
}
}
}
sequence.setSequence(tmp.toString());
- sequence.setStart(newstart);
- sequence.setEnd(newend);
+ sequence.setStart(newStart);
+ sequence.setEnd(newEnd);
+
+ /*
+ * command and Undo share the same dataset sequence if cut was
+ * at start or end of sequence
+ */
+ boolean sameDatasetSequence = false;
if (newDSNeeded)
{
if (sequence.getDatasetSequence() != null)
command.oldds = new SequenceI[command.seqs.length];
}
command.oldds[i] = sequence.getDatasetSequence();
+ sameDatasetSequence = ds == sequence.getDatasetSequence();
+ ds.setSequenceFeatures(sequence.getSequenceFeatures());
sequence.setDatasetSequence(ds);
}
- undoCutFeatures(command, i, start, end);
+ undoCutFeatures(command, command.seqs[i], start, length,
+ sameDatasetSequence);
}
}
adjustAnnotations(command, true, seqWasDeleted, views);
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,
+ String nogapold = AlignSeq.extractGaps(Comparison.GapChars,
new String(command.string[i]));
if (!nogaprep.toLowerCase().equals(nogapold.toLowerCase()))
{
}
// 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)
{
}
}
- final static void undoCutFeatures(Edit command, int index, final int i,
- final int j)
+ /**
+ * Restores features to the state before a Cut.
+ * <ul>
+ * <li>re-add any features deleted by the cut</li>
+ * <li>remove any truncated features created by the cut</li>
+ * <li>shift right any features to the right of the cut</li>
+ * </ul>
+ *
+ * @param command
+ * the Cut command
+ * @param seq
+ * the sequence the Cut applied to
+ * @param start
+ * the start residue position of the cut
+ * @param length
+ * the number of residues cut
+ * @param sameDatasetSequence
+ * true if dataset sequence and frame of reference were left
+ * unchanged by the Cut
+ */
+ final static void undoCutFeatures(Edit command, SequenceI seq,
+ final int start, final int length, boolean sameDatasetSequence)
{
- SequenceI seq = command.seqs[index];
SequenceI sequence = seq.getDatasetSequence();
if (sequence == null)
{
}
/*
- * TODO: shift right features that lie to the right of the restored cut
- * Currently not needed as all features restored with saved dataset sequence
- * nor if no saved dataset sequence (as coordinates left unchanged by Cut)
+ * shift right features that lie to the right of the restored cut (but not
+ * if dataset sequence unchanged - so coordinates were changed by Cut)
*/
+ if (!sameDatasetSequence)
+ {
+ /*
+ * shift right all features right of and not
+ * contiguous with the cut position
+ */
+ seq.getFeatures().shiftFeatures(start + 1, length);
+
+ /*
+ * shift right any features that start at the cut position,
+ * unless they were truncated
+ */
+ List<SequenceFeature> sfs = seq.findFeatures(start, start);
+ for (SequenceFeature sf : sfs)
+ {
+ if (sf.getBegin() == start)
+ {
+ if (!command.truncatedFeatures.containsKey(seq)
+ || !command.truncatedFeatures.get(seq).contains(sf))
+ {
+ /*
+ * feature was shifted left to cut position (not truncated),
+ * so shift it back right
+ */
+ SequenceFeature shifted = new SequenceFeature(sf, sf.getBegin()
+ + length, sf.getEnd() + length, sf.getFeatureGroup(),
+ sf.getScore());
+ seq.addSequenceFeature(shifted);
+ seq.deleteFeature(sf);
+ }
+ }
+ }
+ }
/*
* restore any features that were deleted or truncated
/*
* features deleted by the cut (re-add on Undo)
+ * (including the original of any shortened features)
*/
Map<SequenceI, List<SequenceFeature>> deletedFeatures;
/*
- * features shortened by the cut (delete on Undo)
+ * shortened features added by the cut (delete on Undo)
*/
Map<SequenceI, List<SequenceFeature>> truncatedFeatures;
protected static void cutFeatures(Edit command, SequenceI seq,
int fromPosition, int toPosition, boolean cutIsInternal)
{
+ if (!cutIsInternal)
+ {
+ return;
+ }
List<SequenceFeature> added = new ArrayList<>();
List<SequenceFeature> removed = new ArrayList<>();
cutStartPos, cutEndPos);
/*
+ * add any contact features that span the cut region
+ * (not returned by findFeatures)
+ */
+ for (SequenceFeature contact : featureStore.getContactFeatures())
+ {
+ if (contact.getBegin() < cutStartPos
+ && contact.getEnd() > cutEndPos)
+ {
+ toAmend.add(contact);
+ }
+ }
+
+ /*
* adjust start-end of overlapping features;
* delete features enclosed by the cut;
* delete partially overlapping contact features
* truncate left, adjust end of feature
*/
newBegin = cutIsInternal ? cutStartPos : cutEndPos + 1;
- // newEnd = newBegin + (sfEnd - sfBegin) - overlapsBy;
newEnd = newBegin + sfEnd - cutEndPos - 1;
if (sf.isContactFeature())
{