c1b4daffab3b05573937a1e3c0c400cd367fe2b8
[jalview.git] / src / jalview / commands / EditCommand.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.commands;\r
20 \r
21 import jalview.datamodel.*;\r
22 \r
23 /**\r
24  *\r
25  * <p>Title: EditCommmand</p>\r
26  *\r
27  * <p>Description: Essential information for performing\r
28  * undo and redo for cut/paste insert/delete gap\r
29  * which can be stored in the HistoryList </p>\r
30  *\r
31  * <p>Copyright: Copyright (c) 2006</p>\r
32  *\r
33  * <p>Company: Dundee University</p>\r
34  *\r
35  * @author not attributable\r
36  * @version 1.0\r
37  */\r
38 public class EditCommand implements CommandI\r
39 {\r
40   public static final int INSERT_GAP = 0;\r
41   public static final int DELETE_GAP = 1;\r
42   public static final int CUT = 2;\r
43   public static final int PASTE = 3;\r
44 \r
45   Edit[] edits;\r
46 \r
47   String description;\r
48 \r
49   public EditCommand()\r
50   {}\r
51 \r
52   public EditCommand(String description)\r
53   {\r
54     this.description = description;\r
55   }\r
56 \r
57   public EditCommand( String description,\r
58                       int command,\r
59                       SequenceI[] seqs,\r
60                       int position,\r
61                       int number,\r
62                       AlignmentI al)\r
63    {\r
64      this.description = description;\r
65      if ( command==CUT || command==PASTE)\r
66      {\r
67        edits = new Edit[]{new Edit(command, seqs, position, number, al)};\r
68      }\r
69 \r
70      performEdit(0);\r
71   }\r
72 \r
73 \r
74   public String getDescription()\r
75   {\r
76     return description;\r
77   }\r
78 \r
79   public int getSize()\r
80   {\r
81     return edits==null?0:edits.length;\r
82   }\r
83 \r
84   public AlignmentI getAlignment()\r
85   {\r
86     return edits[0].al;\r
87   }\r
88 \r
89 \r
90   public void appendEdit(int command,\r
91                          SequenceI[] seqs,\r
92                          int position,\r
93                          int number,\r
94                          char gapChar,\r
95                          boolean performEdit)\r
96   {\r
97     Edit edit = new Edit(command, seqs, position, number, gapChar);\r
98 \r
99     if (edits != null)\r
100     {\r
101       Edit[] temp = new Edit[edits.length + 1];\r
102       System.arraycopy(edits, 0, temp, 0, edits.length);\r
103       edits = temp;\r
104       edits[edits.length - 1] = edit;\r
105     }\r
106     else\r
107       edits = new Edit[] {  edit  };\r
108 \r
109     if (performEdit)\r
110       performEdit(edits.length - 1);\r
111   }\r
112 \r
113   void performEdit(int commandIndex)\r
114   {\r
115     int eSize = edits.length;\r
116     for (int e = commandIndex; e < eSize; e++)\r
117     {\r
118       if (edits[e].command==INSERT_GAP)\r
119       {\r
120         insertGap(edits[e]);\r
121       }\r
122       else if (edits[e].command==DELETE_GAP)\r
123       {\r
124         deleteGap(edits[e]);\r
125       }\r
126       else if(edits[e].command==CUT)\r
127       {\r
128         cut(edits[e]);\r
129       }\r
130       else if(edits[e].command==PASTE)\r
131       {\r
132         paste(edits[e]);\r
133       }\r
134     }\r
135   }\r
136 \r
137   public void doCommand()\r
138   {\r
139     performEdit(0);\r
140   }\r
141 \r
142   public void undoCommand()\r
143   {\r
144     int e = 0, eSize = edits.length;\r
145     for (e = eSize-1; e > -1; e--)\r
146     {\r
147       if (edits[e].command==INSERT_GAP)\r
148       {\r
149         deleteGap(edits[e]);\r
150       }\r
151       else if (edits[e].command==DELETE_GAP)\r
152       {\r
153         insertGap(edits[e]);\r
154       }\r
155       else if (edits[e].command==CUT)\r
156       {\r
157         paste(edits[e]);\r
158       }\r
159       else if (edits[e].command==PASTE)\r
160       {\r
161         cut(edits[e]);\r
162       }\r
163     }\r
164   }\r
165 \r
166   void insertGap(Edit command)\r
167   {\r
168     for(int s=0; s<command.seqs.length; s++)\r
169     {\r
170         command.seqs[s].insertCharAt(command.position,\r
171                                      command.number,\r
172                                      command.gapChar);\r
173     }\r
174   }\r
175 \r
176   void deleteGap(Edit command)\r
177   {\r
178     for (int s = 0; s < command.seqs.length; s++)\r
179     {\r
180       command.seqs[s].deleteChars(command.position, command.position+command.number);\r
181     }\r
182   }\r
183 \r
184   void cut(Edit command)\r
185   {\r
186     command.string = new char [command.seqs.length][];\r
187 \r
188     for(int i=0; i<command.seqs.length; i++)\r
189     {\r
190       if(command.seqs[i].getLength()>command.position)\r
191       {\r
192         command.string[i] = command.seqs[i].getSequence(command.position,\r
193             command.position + command.number);\r
194 \r
195         command.seqs[i].deleteChars(command.position,\r
196                                     command.position + command.number);\r
197       }\r
198 \r
199       if(command.seqs[i].getLength()<1)\r
200       {\r
201         command.al.deleteSequence(command.seqs[i]);\r
202       }\r
203 \r
204 \r
205     }\r
206   }\r
207 \r
208   void paste(Edit command)\r
209   {\r
210     StringBuffer tmp;\r
211     for(int i=0; i<command.seqs.length; i++)\r
212     {\r
213       if(command.seqs[i].getLength()<1)\r
214       {\r
215         // ie this sequence was deleted, we need to\r
216         // read it to the alignment\r
217         if (command.alIndex[i] < command.al.getHeight())\r
218           command.al.getSequences().insertElementAt(command.seqs[i],\r
219               command.alIndex[i]);\r
220         else\r
221           command.al.addSequence(command.seqs[i]);\r
222       }\r
223       tmp = new StringBuffer();\r
224       tmp.append(command.seqs[i].getSequence());\r
225 \r
226       if(command.string!=null && command.string[i]!=null)\r
227       {\r
228         if(command.position>=tmp.length())\r
229         {\r
230           //This occurs if padding is on, and residues\r
231           //are removed from end of alignment\r
232           int length = command.position-tmp.length();\r
233           while (length > 0)\r
234           {\r
235             tmp.append(command.gapChar);\r
236             length--;\r
237           }\r
238         }\r
239         tmp.insert(command.position, command.string[i]);\r
240         command.string[i] = null;\r
241       }\r
242       command.seqs[i].setSequence(tmp.toString());\r
243 \r
244 \r
245 \r
246     }\r
247 \r
248     command.string = null;\r
249   }\r
250 \r
251   class Edit\r
252   {\r
253     AlignmentI al;\r
254     int command;\r
255     char [][] string;\r
256     SequenceI[] seqs;\r
257     int [] alIndex;\r
258     int position, number;\r
259     char gapChar;\r
260 \r
261     Edit(int command,\r
262          SequenceI[] seqs,\r
263          int position,\r
264          int number,\r
265          char gapChar)\r
266     {\r
267       this.command = command;\r
268       this.seqs = seqs;\r
269       this.position = position;\r
270       this.number = number;\r
271       this.gapChar = gapChar;\r
272     }\r
273 \r
274 \r
275     Edit(int command,\r
276          SequenceI[] seqs,\r
277          int position,\r
278          int number,\r
279          AlignmentI al)\r
280     {\r
281       this.gapChar = al.getGapCharacter();\r
282       this.command = command;\r
283       this.seqs = seqs;\r
284       this.position = position;\r
285       this.number = number;\r
286       this.al = al;\r
287 \r
288       alIndex = new int[seqs.length];\r
289       for(int i=0; i<seqs.length; i++)\r
290         alIndex[i] = al.findIndex(seqs[i]);\r
291     }\r
292 \r
293   }\r
294 \r
295 }\r