X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=inline;f=src%2Fjalview%2Fcommands%2FEditCommand.java;h=6740b7f5b0da4da853b348af4dd58b9c07285fe1;hb=89077cf6f65c82f9004592a0b4d3bde391163286;hp=7218115323f4e4994994b814cd173b1ccbe42560;hpb=91d2b7cf873f1437a3e21049c5aa6c7a7117e820;p=jalview.git diff --git a/src/jalview/commands/EditCommand.java b/src/jalview/commands/EditCommand.java index 7218115..6740b7f 100644 --- a/src/jalview/commands/EditCommand.java +++ b/src/jalview/commands/EditCommand.java @@ -1,289 +1,900 @@ -/* - * Jalview - A Sequence Alignment Editor and Viewer - * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ -package jalview.commands; - -import jalview.datamodel.*; - -/** - * - *
Title: EditCommmand
- * - *Description: Essential information for performing - * undo and redo for cut/paste insert/delete gap - * which can be stored in the HistoryList
- * - *Copyright: Copyright (c) 2006
- * - *Company: Dundee University
- * - * @author not attributable - * @version 1.0 - */ -public class EditCommand implements CommandI -{ - public static String INSERT_GAP = "InsertGap"; - public static String DELETE_GAP = "DeleteGap"; - public static String CUT = "Cut"; - public static String PASTE = "Paste"; - - Edit[] edits; - - String description; - - public EditCommand() - {} - - public EditCommand(String description) - { - this.description = description; - } - - public EditCommand(String description, - String command, - SequenceI[] seqs, - int position, - int number, - char gapChar) - { - this.description = description; - - if (command.equalsIgnoreCase(INSERT_GAP) - || command.equalsIgnoreCase(DELETE_GAP)) - { - edits = new Edit[] { new Edit(command, seqs, position, number, gapChar)}; - } - - performEdit(0); - } - - public EditCommand( String description, - String command, - SequenceI[] seqs, - int position, - int number, - AlignmentI al) - { - this.description = description; - if ( command.equalsIgnoreCase(CUT) || command.equalsIgnoreCase(PASTE)) - { - edits = new Edit[]{new Edit(command, seqs, position, number, al)}; - } - - performEdit(0); - } - - - public String getDescription() - { - return description; - } - - public int getSize() - { - return edits==null?0:edits.length; - } - - - public void appendEdit(String command, - SequenceI[] seqs, - int position, - int number, - char gapChar, - boolean performEdit) - { - Edit edit = new Edit(command, seqs, position, number, gapChar); - - if (edits != null) - { - Edit[] temp = new Edit[edits.length + 1]; - System.arraycopy(edits, 0, temp, 0, edits.length); - edits = temp; - edits[edits.length - 1] = edit; - } - else - edits = new Edit[] { edit }; - - if (performEdit) - performEdit(edits.length - 1); - } - - void performEdit(int commandIndex) - { - int eSize = edits.length; - for (int e = commandIndex; e < eSize; e++) - { - if (edits[e].command.equals(INSERT_GAP)) - { - insertGap(edits[e]); - } - else if (edits[e].command.equals(DELETE_GAP)) - { - deleteGap(edits[e]); - } - else if(edits[e].command.equals(CUT)) - { - cut(edits[e]); - } - else if(edits[e].command.equals(PASTE)) - { - paste(edits[e]); - } - } - } - - public void doCommand() - { - performEdit(0); - } - - public void undoCommand() - { - int e = 0, eSize = edits.length; - for (e = eSize-1; e > -1; e--) - { - if (edits[e].command.equals(INSERT_GAP)) - { - deleteGap(edits[e]); - } - else if (edits[e].command.equals(DELETE_GAP)) - { - insertGap(edits[e]); - } - else if (edits[e].command.equals(CUT)) - { - paste(edits[e]); - } - else if (edits[e].command.equals(PASTE)) - { - cut(edits[e]); - } - } - } - - void insertGap(Edit command) - { - for(int s=0; sDescription: Essential information for performing + * undo and redo for cut/paste insert/delete gap + * which can be stored in the HistoryList
+ * + *Copyright: Copyright (c) 2006
+ * + *Company: Dundee University
+ * + * @author not attributable + * @version 1.0 + */ +public class EditCommand + implements CommandI +{ + public static final int INSERT_GAP = 0; + 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; + + String description; + + public EditCommand() + {} + + public EditCommand(String description) + { + this.description = description; + } + + public EditCommand(String description, + int command, + SequenceI[] seqs, + int position, + int number, + AlignmentI al) + { + this.description = description; + if (command == CUT || command == PASTE) + { + edits = new Edit[] + { + new Edit(command, seqs, position, number, al)}; + } + + 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() + { + return description; + } + + public int getSize() + { + return edits == null ? 0 : edits.length; + } + + final public AlignmentI getAlignment() + { + 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, AlignmentI[] views) + { + Edit edit = new Edit(command, seqs, position, number, al.getGapCharacter()); + if (al.getHeight() == seqs.length) + { + edit.al = al; + edit.fullAlignmentHeight = true; + } + + if (edits != null) + { + Edit[] temp = new Edit[edits.length + 1]; + System.arraycopy(edits, 0, temp, 0, edits.length); + edits = temp; + edits[edits.length - 1] = edit; + } + else + { + edits = new Edit[] + { + edit}; + } + + if (performEdit) + { + performEdit(edits.length - 1, views); + } + } + + 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]); + break; + case DELETE_GAP: + deleteGap(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(AlignmentI[] views) + { + performEdit(0,views); + } + + 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]); + break; + case DELETE_GAP: + insertGap(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, + command.number, + command.gapChar); + } + + adjustAnnotations(command, true, false, null); + } + + final void deleteGap(Edit command) + { + for (int s = 0; s < command.seqs.length; s++) + { + command.seqs[s].deleteChars(command.position, + command.position + command.number); + } + + adjustAnnotations(command, false, false, null); + } + + void cut(Edit command, AlignmentI[] views) + { + boolean seqDeleted=false; + command.string = new char[command.seqs.length][]; + + for (int i = 0; i < command.seqs.length; i++) + { + if (command.seqs[i].getLength() > command.position) + { + command.string[i] = command.seqs[i].getSequence(command.position, + command.position + command.number); + 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) + { + // 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 (command.oldds==null) + { + 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); + } + } + } + + if (command.seqs[i].getLength() < 1) + { + command.al.deleteSequence(command.seqs[i]); + seqDeleted=true; + } + } + + adjustAnnotations(command, false, seqDeleted, views); + } + + 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 + // read it to the alignment + if (command.alIndex[i] < command.al.getHeight()) + { + command.al.getSequences().insertElementAt(command.seqs[i], + command.alIndex[i]); + } + else + { + command.al.addSequence(command.seqs[i]); + } + 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()) + { + //This occurs if padding is on, and residues + //are removed from end of alignment + int length = command.position - tmp.length(); + while (length > 0) + { + tmp.append(command.gapChar); + 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) + { + if (!newDSNeeded) + { + newDSNeeded = true; + start = command.seqs[i].findPosition(command.position); + end = command.seqs[i].findPosition(command.position + + command.number); + } + 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) + { + 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()); + } + 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, views); + + command.string = null; + } + + void replace(Edit command) + { + StringBuffer tmp; + String oldstring; + int start = command.position; + int end = command.number; + + command.number = start + command.string[0].length; + for (int i = 0; i < command.seqs.length; i++) + { + 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) + { + // only occurs if a sequence was added or deleted. + command.deletedAnnotationRows = new Hashtable(); + } + if (command.fullAlignmentHeight) + { + annotations = command.al.getAlignmentAnnotation(); + } + else + { + int aSize = 0; + AlignmentAnnotation[] tmp; + for (int s = 0; s < command.seqs.length; s++) + { + if (modifyVisibility) + { + // Rows are only removed or added to sequence object. + if (!insert) { + // remove rows + tmp = command.seqs[s].getAnnotation(); + if (tmp!=null) { + int alen=tmp.length; + for (int aa =0; aa