Must be able to find originating alignment modified
[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 String INSERT_GAP = "InsertGap";\r
41   public static String DELETE_GAP = "DeleteGap";\r
42   public static String CUT = "Cut";\r
43   public static String PASTE = "Paste";\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                      String command,\r
59                      SequenceI[] seqs,\r
60                      int position,\r
61                      int number,\r
62                      char gapChar)\r
63   {\r
64     this.description = description;\r
65 \r
66     if (command.equalsIgnoreCase(INSERT_GAP)\r
67         || command.equalsIgnoreCase(DELETE_GAP))\r
68     {\r
69       edits = new Edit[] { new Edit(command, seqs, position, number, gapChar)};\r
70     }\r
71 \r
72     performEdit(0);\r
73   }\r
74 \r
75   public EditCommand( String description,\r
76                       String command,\r
77                       SequenceI[] seqs,\r
78                       int position,\r
79                       int number,\r
80                       AlignmentI al)\r
81    {\r
82      this.description = description;\r
83      if ( command.equalsIgnoreCase(CUT) || command.equalsIgnoreCase(PASTE))\r
84      {\r
85        edits = new Edit[]{new Edit(command, seqs, position, number, al)};\r
86      }\r
87 \r
88      performEdit(0);\r
89   }\r
90 \r
91 \r
92   public String getDescription()\r
93   {\r
94     return description;\r
95   }\r
96 \r
97   public int getSize()\r
98   {\r
99     return edits==null?0:edits.length;\r
100   }\r
101 \r
102   public AlignmentI getAlignment()\r
103   {\r
104     return edits[0].al;\r
105   }\r
106 \r
107 \r
108   public void appendEdit(String command,\r
109                          SequenceI[] seqs,\r
110                          int position,\r
111                          int number,\r
112                          char gapChar,\r
113                          boolean performEdit)\r
114   {\r
115     Edit edit = new Edit(command, seqs, position, number, gapChar);\r
116 \r
117     if (edits != null)\r
118     {\r
119       Edit[] temp = new Edit[edits.length + 1];\r
120       System.arraycopy(edits, 0, temp, 0, edits.length);\r
121       edits = temp;\r
122       edits[edits.length - 1] = edit;\r
123     }\r
124     else\r
125       edits = new Edit[] {  edit  };\r
126 \r
127     if (performEdit)\r
128       performEdit(edits.length - 1);\r
129   }\r
130 \r
131   void performEdit(int commandIndex)\r
132   {\r
133     int eSize = edits.length;\r
134     for (int e = commandIndex; e < eSize; e++)\r
135     {\r
136       if (edits[e].command.equals(INSERT_GAP))\r
137       {\r
138         insertGap(edits[e]);\r
139       }\r
140       else if (edits[e].command.equals(DELETE_GAP))\r
141       {\r
142         deleteGap(edits[e]);\r
143       }\r
144       else if(edits[e].command.equals(CUT))\r
145       {\r
146         cut(edits[e]);\r
147       }\r
148       else if(edits[e].command.equals(PASTE))\r
149       {\r
150         paste(edits[e]);\r
151       }\r
152     }\r
153   }\r
154 \r
155   public void doCommand()\r
156   {\r
157     performEdit(0);\r
158   }\r
159 \r
160   public void undoCommand()\r
161   {\r
162     int e = 0, eSize = edits.length;\r
163     for (e = eSize-1; e > -1; e--)\r
164     {\r
165       if (edits[e].command.equals(INSERT_GAP))\r
166       {\r
167         deleteGap(edits[e]);\r
168       }\r
169       else if (edits[e].command.equals(DELETE_GAP))\r
170       {\r
171         insertGap(edits[e]);\r
172       }\r
173       else if (edits[e].command.equals(CUT))\r
174       {\r
175         paste(edits[e]);\r
176       }\r
177       else if (edits[e].command.equals(PASTE))\r
178       {\r
179         cut(edits[e]);\r
180       }\r
181     }\r
182   }\r
183 \r
184   void insertGap(Edit command)\r
185   {\r
186     for(int s=0; s<command.seqs.length; s++)\r
187     {\r
188         command.seqs[s].insertCharAt(command.position,\r
189                                      command.number,\r
190                                      command.gapChar);\r
191     }\r
192   }\r
193 \r
194   void deleteGap(Edit command)\r
195   {\r
196     for (int s = 0; s < command.seqs.length; s++)\r
197     {\r
198       command.seqs[s].deleteChars(command.position, command.position+command.number);\r
199     }\r
200   }\r
201 \r
202   void cut(Edit command)\r
203   {\r
204     command.string = new String [command.seqs.length];\r
205 \r
206     for(int i=0; i<command.seqs.length; i++)\r
207     {\r
208       if(command.seqs[i].getLength()>command.position)\r
209       {\r
210         command.string[i] = command.seqs[i].getSequence(command.position,\r
211             command.position + command.number);\r
212 \r
213         command.seqs[i].deleteChars(command.position,\r
214                                     command.position + command.number);\r
215       }\r
216 \r
217       if(command.seqs[i].getLength()<1)\r
218       {\r
219         command.al.deleteSequence(command.seqs[i]);\r
220       }\r
221     }\r
222   }\r
223 \r
224   void paste(Edit command)\r
225   {\r
226     StringBuffer tmp;\r
227     for(int i=0; i<command.seqs.length; i++)\r
228     {\r
229       if(command.seqs[i].getLength()<1)\r
230       {\r
231         // ie this sequence was deleted, we need to\r
232         // read it to the alignment\r
233         if (command.alIndex[i] < command.al.getHeight())\r
234           command.al.getSequences().insertElementAt(command.seqs[i],\r
235               command.alIndex[i]);\r
236         else\r
237           command.al.addSequence(command.seqs[i]);\r
238       }\r
239       tmp = new StringBuffer(command.seqs[i].getSequence());\r
240 \r
241       if(command.string!=null && command.string[i]!=null)\r
242       {\r
243         tmp.insert(command.position, command.string[i]);\r
244         command.string[i] = null;\r
245       }\r
246       command.seqs[i].setSequence(tmp.toString());\r
247     }\r
248 \r
249     command.string = null;\r
250   }\r
251 \r
252   class Edit\r
253   {\r
254     AlignmentI al;\r
255     String command;\r
256     String [] string;\r
257     SequenceI[] seqs;\r
258     int [] alIndex;\r
259     int position, number;\r
260     char gapChar;\r
261 \r
262     Edit(String command,\r
263          SequenceI[] seqs,\r
264          int position,\r
265          int number,\r
266          char gapChar)\r
267     {\r
268       this.command = command;\r
269       this.seqs = seqs;\r
270       this.position = position;\r
271       this.number = number;\r
272       this.gapChar = gapChar;\r
273     }\r
274 \r
275 \r
276     Edit(String command,\r
277          SequenceI[] seqs,\r
278          int position,\r
279          int number,\r
280          AlignmentI al)\r
281     {\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       alIndex = new int[seqs.length];\r
288       for(int i=0; i<seqs.length; i++)\r
289         alIndex[i] = al.findIndex(seqs[i]);\r
290     }\r
291 \r
292   }\r
293 \r
294 }\r