1.1 compatible
[jalview.git] / src / jalview / datamodel / ColumnSelection.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 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.datamodel;\r
20 \r
21 import jalview.util.ShiftList;\r
22 \r
23 import java.util.*;\r
24 \r
25 /**\r
26  * NOTE: Columns are zero based.\r
27  */\r
28 public class ColumnSelection\r
29 {\r
30     Vector selected = new Vector();\r
31 \r
32     //Vector of int [] {startCol, endCol}\r
33     Vector hiddenColumns;\r
34 \r
35     /**\r
36      * Add a column to the selection\r
37      *\r
38      * @param col index of column\r
39      */\r
40     public void addElement(int col)\r
41     {\r
42         Integer column = new Integer(col);\r
43         if (!selected.contains(column))\r
44         {\r
45             selected.addElement(column);\r
46         }\r
47     }\r
48 \r
49     /**\r
50      * clears column selection\r
51      */\r
52     public void clear()\r
53     {\r
54         selected.removeAllElements();\r
55     }\r
56 \r
57     /**\r
58      * removes col from selection\r
59      *\r
60      * @param col index of column to be removed\r
61      */\r
62     public void removeElement(int col)\r
63     {\r
64         Integer colInt = new Integer(col);\r
65 \r
66         if (selected.contains(colInt))\r
67         {\r
68             selected.removeElement(colInt);\r
69         }\r
70     }\r
71 \r
72     /**\r
73      * removes a range of columns from the selection\r
74      * @param start int - first column in range to be removed\r
75      * @param end int - last col\r
76      */\r
77     public void removeElements(int start, int end)\r
78     {\r
79       Integer colInt;\r
80       for(int i=start; i<end; i++)\r
81       {\r
82         colInt = new Integer(i);\r
83         if (selected.contains(colInt))\r
84         {\r
85             selected.removeElement(colInt);\r
86         }\r
87       }\r
88     }\r
89     /**\r
90      *\r
91      * @return Vector containing selected columns as Integers\r
92      */\r
93     public Vector getSelected()\r
94     {\r
95       return selected;\r
96     }\r
97 \r
98     /**\r
99      *\r
100      * @param col index to search for in column selection\r
101      *\r
102      * @return true if Integer(col) is in selection.\r
103      */\r
104     public boolean contains(int col)\r
105     {\r
106         return selected.contains(new Integer(col));\r
107     }\r
108 \r
109     /**\r
110      * DOCUMENT ME!\r
111      *\r
112      * @param i DOCUMENT ME!\r
113      *\r
114      * @return DOCUMENT ME!\r
115      */\r
116     public int columnAt(int i)\r
117     {\r
118         return ((Integer) selected.elementAt(i)).intValue();\r
119     }\r
120 \r
121     /**\r
122      * DOCUMENT ME!\r
123      *\r
124      * @return DOCUMENT ME!\r
125      */\r
126     public int size()\r
127     {\r
128         return selected.size();\r
129     }\r
130 \r
131     /**\r
132      * DOCUMENT ME!\r
133      *\r
134      * @return DOCUMENT ME!\r
135      */\r
136     public int getMax()\r
137     {\r
138         int max = -1;\r
139 \r
140         for (int i = 0; i < selected.size(); i++)\r
141         {\r
142             if (columnAt(i) > max)\r
143             {\r
144                 max = columnAt(i);\r
145             }\r
146         }\r
147 \r
148         return max;\r
149     }\r
150 \r
151     /**\r
152      * DOCUMENT ME!\r
153      *\r
154      * @return DOCUMENT ME!\r
155      */\r
156     public int getMin()\r
157     {\r
158         int min = 1000000000;\r
159 \r
160         for (int i = 0; i < selected.size(); i++)\r
161         {\r
162             if (columnAt(i) < min)\r
163             {\r
164                 min = columnAt(i);\r
165             }\r
166         }\r
167 \r
168         return min;\r
169     }\r
170 \r
171 \r
172     /**\r
173      * propagate shift in alignment columns to column selection\r
174      *\r
175      * @param start beginning of edit\r
176      * @param change shift in edit (-ve or +ve number of columns)\r
177      */\r
178     public void compensateForEdit(int start, int change)\r
179     {\r
180         for (int i = 0; i < size(); i++)\r
181         {\r
182             int temp = columnAt(i);\r
183 \r
184             if (temp >= start)\r
185             {\r
186                 selected.setElementAt(new Integer(temp - change), i);\r
187             }\r
188         }\r
189 \r
190         if(hiddenColumns!=null)\r
191         {\r
192           for(int i=0; i<hiddenColumns.size(); i++)\r
193           {\r
194             int[] region = (int[]) hiddenColumns.elementAt(i);\r
195             if(region[0] > start)\r
196             {\r
197               region[0] -= change;\r
198               region[1] -= change;\r
199             }\r
200             if(region[0]<0)\r
201               region[0] = 0;\r
202             if(region[1] <0)\r
203              region[1] = 0;\r
204           }\r
205         }\r
206     }\r
207     public ShiftList compensateForEdits(ShiftList shiftrecord) {\r
208       if (shiftrecord!=null) {\r
209         Vector shifts = shiftrecord.shifts;\r
210         if (shifts!=null && shifts.size()>0) {\r
211           for (int i=0,j=shifts.size(); i<j; i++) {\r
212             int[] sh = (int[]) shifts.elementAt(i);\r
213             compensateForEdit(sh[0], sh[1]);\r
214           }\r
215         }\r
216         return shiftrecord.getInverse();\r
217       }\r
218       return null;\r
219     }\r
220     /**\r
221      * This Method is used to return all the HiddenColumn regions\r
222      * less than the given index.\r
223      * @param end int\r
224      * @return Vector\r
225      */\r
226     public Vector getHiddenColumns()\r
227     {\r
228       return hiddenColumns;\r
229     }\r
230     /**\r
231      * Return absolute column index for a visible column index\r
232      * @param column int column index in alignment view\r
233      * @return alignment column index for column\r
234      */\r
235     public int adjustForHiddenColumns(int column)\r
236     {\r
237       int result = column;\r
238       if (hiddenColumns != null)\r
239       {\r
240         for (int i = 0; i < hiddenColumns.size(); i++)\r
241         {\r
242           int[] region = (int[]) hiddenColumns.elementAt(i);\r
243           if (result >= region[0])\r
244           {\r
245             result += region[1] - region[0] + 1;\r
246           }\r
247         }\r
248       }\r
249       return result;\r
250     }\r
251 \r
252     /**\r
253      * Use this method to find out where a visible column is in the alignment\r
254      * when hidden columns exist\r
255      * @param hiddenColumn int\r
256      * @return int\r
257      */\r
258     public int findColumnPosition(int hiddenColumn)\r
259     {\r
260       int result = hiddenColumn;\r
261       if (hiddenColumns != null)\r
262       {\r
263         int index = 0;\r
264         int gaps = 0;\r
265         do\r
266         {\r
267           int[] region = (int[]) hiddenColumns.elementAt(index);\r
268           if (hiddenColumn > region[1])\r
269           {\r
270             result -= region[1]+1-region[0];\r
271           }\r
272           index++;\r
273         }\r
274         while (index < hiddenColumns.size());\r
275 \r
276         result -= gaps;\r
277       }\r
278 \r
279       return result;\r
280     }\r
281 \r
282     /**\r
283      * Use this method to determine where the next hiddenRegion starts\r
284     */\r
285     public int findHiddenRegionPosition(int hiddenRegion)\r
286     {\r
287       int result = 0;\r
288       if (hiddenColumns != null)\r
289       {\r
290         int index = 0;\r
291         int gaps = 0;\r
292         do\r
293         {\r
294           int[] region = (int[]) hiddenColumns.elementAt(index);\r
295           if(hiddenRegion==0)\r
296           {\r
297             return region[0];\r
298           }\r
299 \r
300             gaps +=  region[1] +1 - region[0];\r
301             result = region[1] +1;\r
302             index++;\r
303         }\r
304         while(index < hiddenRegion+1);\r
305 \r
306         result -= gaps;\r
307       }\r
308 \r
309       return result;\r
310     }\r
311 \r
312     /**\r
313      * THis method returns the rightmost limit of a\r
314      * region of an alignment with hidden columns.\r
315      * In otherwords, the next hidden column.\r
316      * @param index int\r
317      */\r
318     public int getHiddenBoundaryRight(int alPos)\r
319     {\r
320       if (hiddenColumns != null)\r
321       {\r
322         int index = 0;\r
323         do\r
324         {\r
325           int[] region = (int[]) hiddenColumns.elementAt(index);\r
326           if(alPos < region[0])\r
327             return region[0];\r
328 \r
329           index++;\r
330         }\r
331         while(index < hiddenColumns.size());\r
332       }\r
333 \r
334       return alPos;\r
335 \r
336     }\r
337     /**\r
338      * THis method returns the rightmost limit of a\r
339      * region of an alignment with hidden columns.\r
340      * In otherwords, the next hidden column.\r
341      * @param index int\r
342      */\r
343     public int getHiddenBoundaryLeft(int alPos)\r
344     {\r
345       if (hiddenColumns != null)\r
346       {\r
347         int index = hiddenColumns.size()-1;\r
348         do\r
349         {\r
350           int[] region = (int[]) hiddenColumns.elementAt(index);\r
351           if(alPos > region[1])\r
352             return region[1];\r
353 \r
354           index--;\r
355         }\r
356         while(index >-1);\r
357       }\r
358 \r
359       return alPos;\r
360 \r
361     }\r
362 \r
363     public void hideSelectedColumns()\r
364     {\r
365       while (size() > 0)\r
366       {\r
367         int column = ( (Integer) getSelected().firstElement()).intValue();\r
368         hideColumns(column);\r
369       }\r
370 \r
371     }\r
372 \r
373     public void hideColumns(int start, int end)\r
374     {\r
375       if(hiddenColumns==null)\r
376         hiddenColumns = new Vector();\r
377 \r
378       boolean added = false;\r
379       boolean overlap = false;\r
380 \r
381       for (int i = 0; i < hiddenColumns.size(); i++)\r
382       {\r
383         int[] region = (int[]) hiddenColumns.elementAt(i);\r
384         if ( start<=region[1] && end>=region[0])\r
385         {\r
386           hiddenColumns.removeElementAt(i);\r
387           overlap = true;\r
388           break;\r
389         }\r
390         else if (end < region[0] && start < region[0])\r
391         {\r
392           hiddenColumns.insertElementAt(new int[]\r
393                                         {start, end}, i);\r
394           added = true;\r
395           break;\r
396         }\r
397       }\r
398 \r
399       if(overlap)\r
400       {\r
401          hideColumns(start, end);\r
402       }\r
403       else if (!added)\r
404         hiddenColumns.addElement(new int[] {start, end});\r
405 \r
406     }\r
407 \r
408     /**\r
409      * This method will find a range of selected columns\r
410      * around the column specified\r
411      * @param res int\r
412      */\r
413     public void hideColumns(int col)\r
414     {\r
415       // First find out range of columns to hide\r
416       int min = col, max = col+1;\r
417       while( contains(min) )\r
418       {  removeElement(min); min --;  }\r
419 \r
420       while( contains(max) )\r
421       { removeElement(max);  max ++;  }\r
422 \r
423       min++; max--;\r
424 \r
425       hideColumns(min, max);\r
426     }\r
427 \r
428     public void revealAllHiddenColumns()\r
429     {\r
430       if(hiddenColumns!=null)\r
431       {\r
432         for (int i = 0; i < hiddenColumns.size(); i++)\r
433         {\r
434           int[] region = (int[]) hiddenColumns.elementAt(i);\r
435           for (int j = region[0]; j < region[1]+1; j++)\r
436           {\r
437             addElement(j);\r
438           }\r
439         }\r
440       }\r
441 \r
442       hiddenColumns = null;\r
443     }\r
444 \r
445     public void revealHiddenColumns(int res)\r
446     {\r
447       for(int i=0; i<hiddenColumns.size(); i++)\r
448       {\r
449         int [] region = (int[])hiddenColumns.elementAt(i);\r
450         if( res == region[0])\r
451         {\r
452           for (int j = region[0]; j < region[1]+1; j++)\r
453           {\r
454             addElement(j);\r
455           }\r
456 \r
457           hiddenColumns.removeElement(region);\r
458           break;\r
459         }\r
460       }\r
461       if(hiddenColumns.size()==0)\r
462         hiddenColumns = null;\r
463     }\r
464 \r
465     public boolean isVisible(int column)\r
466     {\r
467       for(int i=0; i<hiddenColumns.size(); i++)\r
468       {\r
469         int [] region = (int[])hiddenColumns.elementAt(i);\r
470         if( column >= region[0] && column <= region[1])\r
471         {\r
472           return false;\r
473         }\r
474       }\r
475       return true;\r
476     }\r
477     /**\r
478      * Copy constructor\r
479      * @param copy\r
480      */\r
481     public ColumnSelection(ColumnSelection copy) {\r
482       if (copy!=null) {\r
483         if (copy.selected!=null) {\r
484           selected = new Vector();\r
485           for (int i=0,j=copy.selected.size(); i<j; i++) {\r
486             selected.setElementAt(((Integer) copy.selected.elementAt(i)), i);\r
487           }\r
488         }\r
489         if (copy.hiddenColumns!=null) {\r
490           hiddenColumns=new Vector();\r
491           for (int i=0,j=copy.hiddenColumns.size(); i<j; i++) {\r
492             int[] rh,cp;\r
493             rh = (int[])copy.hiddenColumns.elementAt(i);\r
494             if (rh!=null) {\r
495               cp = new int[rh.length];\r
496               System.arraycopy(rh, 0, cp, 0, rh.length);\r
497               hiddenColumns.setElementAt(cp, i);\r
498             }\r
499           }\r
500         }\r
501       }\r
502     }\r
503 \r
504   /**\r
505    * ColumnSelection\r
506    */\r
507   public ColumnSelection()\r
508   {\r
509   }\r
510 }\r