Commands which can be done, or undone
[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 \r
103   public void appendEdit(String command,\r
104                          SequenceI[] seqs,\r
105                          int position,\r
106                          int number,\r
107                          char gapChar,\r
108                          boolean performEdit)\r
109   {\r
110     Edit edit = new Edit(command, seqs, position, number, gapChar);\r
111 \r
112     if (edits != null)\r
113     {\r
114       Edit[] temp = new Edit[edits.length + 1];\r
115       System.arraycopy(edits, 0, temp, 0, edits.length);\r
116       edits = temp;\r
117       edits[edits.length - 1] = edit;\r
118     }\r
119     else\r
120       edits = new Edit[] {  edit  };\r
121 \r
122     if (performEdit)\r
123       performEdit(edits.length - 1);\r
124   }\r
125 \r
126   void performEdit(int commandIndex)\r
127   {\r
128     int eSize = edits.length;\r
129     for (int e = commandIndex; e < eSize; e++)\r
130     {\r
131       if (edits[e].command.equals(INSERT_GAP))\r
132       {\r
133         insertGap(edits[e]);\r
134       }\r
135       else if (edits[e].command.equals(DELETE_GAP))\r
136       {\r
137         deleteGap(edits[e]);\r
138       }\r
139       else if(edits[e].command.equals(CUT))\r
140       {\r
141         cut(edits[e]);\r
142       }\r
143       else if(edits[e].command.equals(PASTE))\r
144       {\r
145         paste(edits[e]);\r
146       }\r
147     }\r
148   }\r
149 \r
150   public void doCommand()\r
151   {\r
152     performEdit(0);\r
153   }\r
154 \r
155   public void undoCommand()\r
156   {\r
157     int e = 0, eSize = edits.length;\r
158     for (e = eSize-1; e > -1; e--)\r
159     {\r
160       if (edits[e].command.equals(INSERT_GAP))\r
161       {\r
162         deleteGap(edits[e]);\r
163       }\r
164       else if (edits[e].command.equals(DELETE_GAP))\r
165       {\r
166         insertGap(edits[e]);\r
167       }\r
168       else if (edits[e].command.equals(CUT))\r
169       {\r
170         paste(edits[e]);\r
171       }\r
172       else if (edits[e].command.equals(PASTE))\r
173       {\r
174         cut(edits[e]);\r
175       }\r
176     }\r
177   }\r
178 \r
179   void insertGap(Edit command)\r
180   {\r
181     for(int s=0; s<command.seqs.length; s++)\r
182     {\r
183         command.seqs[s].insertCharAt(command.position,\r
184                                      command.number,\r
185                                      command.gapChar);\r
186     }\r
187   }\r
188 \r
189   void deleteGap(Edit command)\r
190   {\r
191     for (int s = 0; s < command.seqs.length; s++)\r
192     {\r
193       command.seqs[s].deleteChars(command.position, command.position+command.number);\r
194     }\r
195   }\r
196 \r
197   void cut(Edit command)\r
198   {\r
199     command.string = new String [command.seqs.length];\r
200 \r
201     for(int i=0; i<command.seqs.length; i++)\r
202     {\r
203       command.string[i] = command.seqs[i].getSequence(command.position,\r
204                                            command.position + command.number);\r
205 \r
206       command.seqs[i].deleteChars(command.position,\r
207                                   command.position+command.number);\r
208 \r
209       if(command.seqs[i].getLength()<1)\r
210       {\r
211         command.al.deleteSequence(command.seqs[i]);\r
212       }\r
213     }\r
214   }\r
215 \r
216   void paste(Edit command)\r
217   {\r
218     StringBuffer tmp;\r
219     for(int i=0; i<command.seqs.length; i++)\r
220     {\r
221       if(command.seqs[i].getLength()<1)\r
222       {\r
223         // ie this sequence was deleted, we need to\r
224         // read it to the alignment\r
225         if (command.alIndex[i] < command.al.getHeight())\r
226           command.al.getSequences().insertElementAt(command.seqs[i],\r
227               command.alIndex[i]);\r
228         else\r
229           command.al.addSequence(command.seqs[i]);\r
230       }\r
231       tmp = new StringBuffer(command.seqs[i].getSequence());\r
232       if(command.string!=null)\r
233       {\r
234         tmp.insert(command.position, command.string[i]);\r
235         command.string[i] = null;\r
236       }\r
237       command.seqs[i].setSequence(tmp.toString());\r
238     }\r
239 \r
240     command.string = null;\r
241   }\r
242 \r
243   class Edit\r
244   {\r
245     AlignmentI al;\r
246     String command;\r
247     String [] string;\r
248     SequenceI[] seqs;\r
249     int [] alIndex;\r
250     int position, number;\r
251     char gapChar;\r
252 \r
253     Edit(String command,\r
254          SequenceI[] seqs,\r
255          int position,\r
256          int number,\r
257          char gapChar)\r
258     {\r
259       this.command = command;\r
260       this.seqs = seqs;\r
261       this.position = position;\r
262       this.number = number;\r
263       this.gapChar = gapChar;\r
264     }\r
265 \r
266 \r
267     Edit(String command,\r
268          SequenceI[] seqs,\r
269          int position,\r
270          int number,\r
271          AlignmentI al)\r
272     {\r
273       this.command = command;\r
274       this.seqs = seqs;\r
275       this.position = position;\r
276       this.number = number;\r
277       this.al = al;\r
278       alIndex = new int[seqs.length];\r
279       for(int i=0; i<seqs.length; i++)\r
280         alIndex[i] = al.findIndex(seqs[i]);\r
281     }\r
282 \r
283   }\r
284 \r
285 }\r