/*
* 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.*;
import java.util.Hashtable;
/**
*
*
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 final int INSERT_GAP = 0;
public static final int DELETE_GAP = 1;
public static final int CUT = 2;
public static final int PASTE = 3;
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);
}
final public String getDescription()
{
return description;
}
public int getSize()
{
return edits==null?0:edits.length;
}
final public AlignmentI getAlignment()
{
return edits[0].al;
}
final public void appendEdit(int command,
SequenceI[] seqs,
int position,
int number,
AlignmentI al,
boolean performEdit)
{
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);
}
final void performEdit(int commandIndex)
{
int eSize = edits.length;
for (int e = commandIndex; e < eSize; e++)
{
if (edits[e].command==INSERT_GAP)
{
insertGap(edits[e]);
}
else if (edits[e].command==DELETE_GAP)
{
deleteGap(edits[e]);
}
else if(edits[e].command==CUT)
{
cut(edits[e]);
}
else if(edits[e].command==PASTE)
{
paste(edits[e]);
}
}
}
final public void doCommand()
{
performEdit(0);
}
final public void undoCommand()
{
int e = 0, eSize = edits.length;
for (e = eSize-1; e > -1; e--)
{
if (edits[e].command==INSERT_GAP)
{
deleteGap(edits[e]);
}
else if (edits[e].command==DELETE_GAP)
{
insertGap(edits[e]);
}
else if (edits[e].command==CUT)
{
paste(edits[e]);
}
else if (edits[e].command==PASTE)
{
cut(edits[e]);
}
}
}
final void insertGap(Edit command)
{
for(int s=0; scommand.position)
{
command.string[i] = command.seqs[i].getSequence(command.position,
command.position + command.number);
if(command.seqs[i].getDatasetSequence()!=null
|| command.seqs[i].getSequenceFeatures()!=null)
{
for (int s = command.position; s < command.position + command.number; s++)
{
if (jalview.schemes.ResidueProperties
.aaIndex[command.seqs[i].getCharAt(s)] != 23)
{
adjustFeatures(command, i,
command.seqs[i].findPosition(command.position),
command.seqs[i].findPosition(command.position +
command.number),
false);
break;
}
}
}
command.seqs[i].deleteChars(command.position,
command.position + command.number);
}
if(command.seqs[i].getLength()<1)
{
command.al.deleteSequence(command.seqs[i]);
}
}
adjustAnnotations(command, false);
}
void paste(Edit command)
{
StringBuffer tmp;
boolean newDSNeeded;
int start=0, end=0;
for(int i=0; i=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)
{
newDSNeeded = true;
start = command.seqs[i].findPosition(command.position);
end = command.seqs[i].findPosition(command.position+command.number);
break;
}
}
command.string[i] = null;
}
command.seqs[i].setSequence(tmp.toString());
if(newDSNeeded)
{
if (command.seqs[i].getDatasetSequence() != null)
{
Sequence 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());
command.seqs[i].setDatasetSequence(ds);
}
adjustFeatures(command, i, start, end, true);
}
}
adjustAnnotations(command, true);
command.string = null;
}
final void adjustAnnotations(Edit command, boolean insert)
{
AlignmentAnnotation [] annotations = null;
if (command.fullAlignmentHeight)
{
annotations = command.al.getAlignmentAnnotation();
}
else
{
int aSize = 0;
AlignmentAnnotation [] tmp;
for(int s=0; s j)
{
sf[s].setBegin(copy.getBegin() - cSize);
sf[s].setEnd(copy.getEnd() - cSize);
continue;
}
if (sf[s].getBegin() >= i)
sf[s].setBegin(i);
if (sf[s].getEnd() < j)
sf[s].setEnd(j - 1);
sf[s].setEnd(sf[s].getEnd() - (cSize));
if (sf[s].getBegin() > sf[s].getEnd())
sequence.deleteFeature(sf[s]);
}
if (command.editedFeatures == null)
command.editedFeatures = new Hashtable();
command.editedFeatures.put(seq, oldsf);
}
class Edit
{
boolean fullAlignmentHeight = false;
Hashtable deletedAnnotations;
Hashtable editedFeatures;
AlignmentI al;
int command;
char [][] string;
SequenceI[] seqs;
int [] alIndex;
int position, number;
char gapChar;
Edit(int command,
SequenceI[] seqs,
int position,
int number,
char gapChar)
{
this.command = command;
this.seqs = seqs;
this.position = position;
this.number = number;
this.gapChar = gapChar;
}
Edit(int command,
SequenceI[] seqs,
int position,
int number,
AlignmentI al)
{
this.gapChar = al.getGapCharacter();
this.command = command;
this.seqs = seqs;
this.position = position;
this.number = number;
this.al = al;
alIndex = new int[seqs.length];
for(int i=0; i