X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fcommands%2FEditCommand.java;h=e859e3efd0342adead51c7f389302b5af3e15a55;hb=17f7dd1302e3337df9b04a811b5d45ab102ac02b;hp=45b19afd180419e65aa67bde723fae03dd4b0912;hpb=2a6873d5bfdd3c0f501545dbf4b07c184a7352b5;p=jalview.git diff --git a/src/jalview/commands/EditCommand.java b/src/jalview/commands/EditCommand.java index 45b19af..e859e3e 100644 --- a/src/jalview/commands/EditCommand.java +++ b/src/jalview/commands/EditCommand.java @@ -44,6 +44,7 @@ public class EditCommand public static final int DELETE_GAP = 1; public static final int CUT = 2; public static final int PASTE = 3; + public static final int REPLACE = 4; Edit[] edits; @@ -72,7 +73,25 @@ public class EditCommand new Edit(command, seqs, position, number, al)}; } - performEdit(0); + performEdit(0, null); + } + + public EditCommand(String description, + int command, + String replace, + SequenceI[] seqs, + int position, + int number, + AlignmentI al) + { + this.description = description; + if (command == REPLACE) + { + edits = new Edit[] + { new Edit(command, seqs, position, number, al, replace)}; + } + + performEdit(0, null); } final public String getDescription() @@ -90,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) @@ -120,65 +169,70 @@ 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++) { - if (edits[e].command == INSERT_GAP) + switch(edits[e].command) { + case INSERT_GAP: insertGap(edits[e]); - } - else if (edits[e].command == DELETE_GAP) - { + break; + case DELETE_GAP: deleteGap(edits[e]); - } - else if (edits[e].command == CUT) - { - cut(edits[e]); - } - else if (edits[e].command == PASTE) - { - paste(edits[e]); + break; + case CUT: + cut(edits[e], views); + break; + case PASTE: + paste(edits[e], views); + break; + case REPLACE: + replace(edits[e]); + break; } } } - 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--) { - if (edits[e].command == INSERT_GAP) + switch (edits[e].command) { + case INSERT_GAP: deleteGap(edits[e]); - } - else if (edits[e].command == DELETE_GAP) - { + break; + case DELETE_GAP: insertGap(edits[e]); - } - else if (edits[e].command == CUT) - { - paste(edits[e]); - } - else if (edits[e].command == PASTE) - { - cut(edits[e]); + break; + case CUT: + paste(edits[e], views); + break; + case PASTE: + cut(edits[e], views); + break; + case REPLACE: + replace(edits[e]); + break; } } } final void insertGap(Edit command) { + for (int s = 0; s < command.seqs.length; s++) { command.seqs[s].insertCharAt(command.position, @@ -186,7 +240,7 @@ public class EditCommand command.gapChar); } - adjustAnnotations(command, true, false); + adjustAnnotations(command, true, false, null); } final void deleteGap(Edit command) @@ -197,10 +251,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][]; @@ -211,27 +265,36 @@ public class EditCommand { 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) + { + // 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) { - for (int s = command.position; s < command.position + command.number; - s++) + // 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) @@ -241,19 +304,22 @@ 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; + 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 @@ -269,9 +335,13 @@ public class EditCommand } 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()) @@ -286,50 +356,109 @@ public class EditCommand } } 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) + void replace(Edit command) { + StringBuffer tmp; + String oldstring; + int start = command.position; + int end = command.number; + // TODO TUTORIAL - Fix for replacement with different length of sequence (or whole sequence) + // TODO Jalview 2.4 bugfix change to an aggregate command - original sequence string is cut, new string is pasted in. + command.number = start + command.string[0].length; + for (int i = 0; i < command.seqs.length; i++) + { + /** cut + * addHistoryItem(new EditCommand("Cut Sequences", + EditCommand.CUT, + cut, + sg.getStartRes(), + sg.getEndRes()-sg.getStartRes()+1, + viewport.alignment)); + + */ + /** then + * addHistoryItem(new EditCommand( + "Add sequences", + EditCommand.PASTE, + sequences, + 0, + alignment.getWidth(), + alignment) + ); + + */ + oldstring = command.seqs[i].getSequenceAsString(); + tmp = new StringBuffer(oldstring.substring(0, start)); + tmp.append(command.string[i]); + tmp.append(oldstring.substring(end)); + command.seqs[i].setSequence(tmp.toString()); + command.string[i] = oldstring.substring(start, end).toCharArray(); + tmp = null; + oldstring = null; + } + } + final void adjustAnnotations(Edit command, boolean insert, boolean modifyVisibility, AlignmentI[] views) + { AlignmentAnnotation[] annotations = null; if (modifyVisibility && !insert) @@ -354,12 +483,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 aSize) + if (command.position + command.number >= aSize) { tSize = aSize; } else { - tSize = aSize - command.number + command.position; + tSize = aSize - command.number; } } else @@ -464,9 +654,9 @@ public class EditCommand tSize = aSize; } temp = new Annotation[tSize]; - } + if (insert) { if (command.position < annotations[a].annotations.length) @@ -529,7 +719,7 @@ public class EditCommand 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) { @@ -658,6 +848,7 @@ public class EditCommand class Edit { + public SequenceI[] oldds; boolean fullAlignmentHeight = false; Hashtable deletedAnnotationRows; Hashtable deletedAnnotations; @@ -704,6 +895,27 @@ public class EditCommand fullAlignmentHeight = (al.getHeight() == seqs.length); } - } + Edit(int command, + SequenceI[] seqs, + int position, + int number, + AlignmentI al, + 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++) + { + string[i] = replace.toCharArray(); + } + + fullAlignmentHeight = (al.getHeight() == seqs.length); + } + } }