JAL-2050 JAL-1722 new getSelectedRange() method to quickly hide selected columns
[jalview.git] / test / jalview / datamodel / ColumnSelectionTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.datamodel;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertSame;
26 import static org.testng.AssertJUnit.assertTrue;
27
28 import java.util.Arrays;
29 import java.util.List;
30
31 import org.testng.annotations.Test;
32
33 public class ColumnSelectionTest
34 {
35
36   @Test(groups = { "Functional" })
37   public void testAddElement()
38   {
39     ColumnSelection cs = new ColumnSelection();
40     cs.addElement(2);
41     cs.addElement(5);
42     cs.addElement(3);
43     cs.addElement(5); // ignored
44     List<Integer> sel = cs.getSelected();
45     assertEquals("[2, 5, 3]", sel.toString());
46   }
47
48   /**
49    * Test the remove method - in particular to verify that remove(int i) removes
50    * the element whose value is i, _NOT_ the i'th element.
51    */
52   @Test(groups = { "Functional" })
53   public void testRemoveElement()
54   {
55     ColumnSelection cs = new ColumnSelection();
56     cs.addElement(2);
57     cs.addElement(5);
58
59     // removing elements not in the list has no effect
60     cs.removeElement(0);
61     cs.removeElement(1);
62     List<Integer> sel = cs.getSelected();
63     assertEquals(2, sel.size());
64     assertEquals(new Integer(2), sel.get(0));
65     assertEquals(new Integer(5), sel.get(1));
66
67     // removing an element in the list removes it
68     cs.removeElement(2);
69     assertEquals(1, sel.size());
70     assertEquals(new Integer(5), sel.get(0));
71   }
72
73   /**
74    * Test the method that finds the visible column position of an alignment
75    * column, allowing for hidden columns.
76    */
77   @Test(groups = { "Functional" })
78   public void testFindColumnPosition()
79   {
80     ColumnSelection cs = new ColumnSelection();
81     assertEquals(5, cs.findColumnPosition(5));
82
83     // hiding column 6 makes no difference
84     cs.hideColumns(6, 6);
85     assertEquals(5, cs.findColumnPosition(5));
86
87     // hiding column 4 moves column 5 to column 4
88     cs.hideColumns(4, 4);
89     assertEquals(4, cs.findColumnPosition(5));
90
91     // hiding columns 1 and 2 moves column 5 to column 2
92     cs.hideColumns(1, 2);
93     assertEquals(2, cs.findColumnPosition(5));
94   }
95
96   @Test(groups = { "Functional" })
97   public void testHideColumns()
98   {
99     ColumnSelection cs = new ColumnSelection();
100     cs.hideColumns(5);
101     List<int[]> hidden = cs.getHiddenColumns();
102     assertEquals(1, hidden.size());
103     assertEquals("[5, 5]", Arrays.toString(hidden.get(0)));
104
105     cs.hideColumns(3);
106     assertEquals(2, hidden.size());
107     // two hidden ranges, in order:
108     assertSame(hidden, cs.getHiddenColumns());
109     assertEquals("[3, 3]", Arrays.toString(hidden.get(0)));
110     assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
111
112     // hiding column 4 expands [3, 3] to [3, 4]
113     // not fancy enough to coalesce this into [3, 5] though
114     cs.hideColumns(4);
115     hidden = cs.getHiddenColumns();
116     assertEquals(2, hidden.size());
117     assertEquals("[3, 4]", Arrays.toString(hidden.get(0)));
118     assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
119
120     // clear hidden columns (note they are added to selected)
121     cs.revealAllHiddenColumns();
122     // it is now actually null but getter returns an empty list
123     assertTrue(cs.getHiddenColumns().isEmpty());
124
125     cs.hideColumns(3, 6);
126     hidden = cs.getHiddenColumns();
127     int[] firstHiddenRange = hidden.get(0);
128     assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
129
130     // adding a subrange of already hidden should do nothing
131     cs.hideColumns(4, 5);
132     assertEquals(1, hidden.size());
133     assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
134     cs.hideColumns(3, 5);
135     assertEquals(1, hidden.size());
136     assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
137     cs.hideColumns(4, 6);
138     assertEquals(1, hidden.size());
139     assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
140     cs.hideColumns(3, 6);
141     assertEquals(1, hidden.size());
142     assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
143
144     cs.revealAllHiddenColumns();
145     cs.hideColumns(2, 4);
146     hidden = cs.getHiddenColumns();
147     assertEquals(1, hidden.size());
148     assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
149
150     // extend contiguous with 2 positions overlap
151     cs.hideColumns(3, 5);
152     assertEquals(1, hidden.size());
153     assertEquals("[2, 5]", Arrays.toString(hidden.get(0)));
154
155     // extend contiguous with 1 position overlap
156     cs.hideColumns(5, 6);
157     assertEquals(1, hidden.size());
158     assertEquals("[2, 6]", Arrays.toString(hidden.get(0)));
159
160     // extend contiguous with overlap both ends:
161     cs.hideColumns(1, 7);
162     assertEquals(1, hidden.size());
163     assertEquals("[1, 7]", Arrays.toString(hidden.get(0)));
164   }
165
166   /**
167    * Test the method that hides a specified column including any adjacent
168    * selected columns. This is a convenience method for the case where multiple
169    * column regions are selected and then hidden using menu option View | Hide |
170    * Selected Columns.
171    */
172   @Test(groups = { "Functional" })
173   public void testHideColumns_withSelection()
174   {
175     ColumnSelection cs = new ColumnSelection();
176     // select columns 4-6
177     cs.addElement(4);
178     cs.addElement(5);
179     cs.addElement(6);
180     // hide column 5 (and adjacent):
181     cs.hideColumns(5);
182     // 4,5,6 now hidden:
183     List<int[]> hidden = cs.getHiddenColumns();
184     assertEquals(1, hidden.size());
185     assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
186     // none now selected:
187     assertTrue(cs.getSelected().isEmpty());
188
189     // repeat, hiding column 4 (5 and 6)
190     cs = new ColumnSelection();
191     cs.addElement(4);
192     cs.addElement(5);
193     cs.addElement(6);
194     cs.hideColumns(4);
195     hidden = cs.getHiddenColumns();
196     assertEquals(1, hidden.size());
197     assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
198     assertTrue(cs.getSelected().isEmpty());
199
200     // repeat, hiding column (4, 5 and) 6
201     cs = new ColumnSelection();
202     cs.addElement(4);
203     cs.addElement(5);
204     cs.addElement(6);
205     cs.hideColumns(6);
206     hidden = cs.getHiddenColumns();
207     assertEquals(1, hidden.size());
208     assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
209     assertTrue(cs.getSelected().isEmpty());
210
211     // repeat, with _only_ adjacent columns selected
212     cs = new ColumnSelection();
213     cs.addElement(4);
214     cs.addElement(6);
215     cs.hideColumns(5);
216     hidden = cs.getHiddenColumns();
217     assertEquals(1, hidden.size());
218     assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
219     assertTrue(cs.getSelected().isEmpty());
220   }
221
222   /**
223    * Test the method that hides all (possibly disjoint) selected column ranges
224    */
225   @Test(groups = { "Functional" })
226   public void testHideSelectedColumns()
227   {
228     ColumnSelection cs = new ColumnSelection();
229     int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
230     for (int col : sel)
231     {
232       cs.addElement(col);
233     }
234     cs.hideColumns(15, 18);
235
236     cs.hideSelectedColumns();
237     assertTrue(cs.getSelected().isEmpty());
238     List<int[]> hidden = cs.getHiddenColumns();
239     assertEquals(4, hidden.size());
240     assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
241     assertEquals("[7, 9]", Arrays.toString(hidden.get(1)));
242     assertEquals("[15, 18]", Arrays.toString(hidden.get(2)));
243     assertEquals("[20, 22]", Arrays.toString(hidden.get(3)));
244   }
245
246   /**
247    * Test the method that gets runs of selected columns ordered by column. If
248    * this fails, HideSelectedColumns may also fail
249    */
250   @Test(groups = { "Functional" })
251   public void testgetSelectedRanges()
252   {
253     ColumnSelection cs = new ColumnSelection();
254     int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
255     for (int col : sel)
256     {
257       cs.addElement(col);
258     }
259     List<int[]> range;
260     range = cs.getSelectedRanges();
261     assertEquals(3, range.size());
262     assertEquals("[2, 4]", Arrays.toString(range.get(0)));
263     assertEquals("[7, 9]", Arrays.toString(range.get(1)));
264     assertEquals("[20, 22]", Arrays.toString(range.get(2)));
265     cs.addElement(0);
266     cs.addElement(1);
267     range = cs.getSelectedRanges();
268     assertEquals(3, range.size());
269     assertEquals("[0, 4]", Arrays.toString(range.get(0)));
270   }
271
272   /**
273    * Test the method that reveals a range of hidden columns given the start
274    * column of the range
275    */
276   @Test(groups = { "Functional" })
277   public void testRevealHiddenColumns()
278   {
279     ColumnSelection cs = new ColumnSelection();
280     cs.hideColumns(5, 8);
281     cs.addElement(10);
282     cs.revealHiddenColumns(5);
283     // hidden columns list now null but getter returns empty list:
284     assertTrue(cs.getHiddenColumns().isEmpty());
285     // revealed columns are marked as selected (added to selection):
286     assertEquals("[10, 5, 6, 7, 8]", cs.getSelected().toString());
287
288     // calling with a column other than the range start does nothing:
289     cs = new ColumnSelection();
290     cs.hideColumns(5, 8);
291     List<int[]> hidden = cs.getHiddenColumns();
292     cs.revealHiddenColumns(6);
293     assertSame(hidden, cs.getHiddenColumns());
294     assertTrue(cs.getSelected().isEmpty());
295   }
296
297   @Test(groups = { "Functional" })
298   public void testRevealAllHiddenColumns()
299   {
300     ColumnSelection cs = new ColumnSelection();
301     cs.hideColumns(5, 8);
302     cs.hideColumns(2, 3);
303     cs.addElement(11);
304     cs.addElement(1);
305     cs.revealAllHiddenColumns();
306
307     /*
308      * revealing hidden columns adds them (in order) to the (unordered)
309      * selection list
310      */
311     assertTrue(cs.getHiddenColumns().isEmpty());
312     assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]", cs.getSelected().toString());
313   }
314
315   @Test(groups = { "Functional" })
316   public void testIsVisible()
317   {
318     ColumnSelection cs = new ColumnSelection();
319     cs.hideColumns(2, 4);
320     cs.hideColumns(6, 7);
321     assertTrue(cs.isVisible(0));
322     assertTrue(cs.isVisible(-99));
323     assertTrue(cs.isVisible(1));
324     assertFalse(cs.isVisible(2));
325     assertFalse(cs.isVisible(3));
326     assertFalse(cs.isVisible(4));
327     assertTrue(cs.isVisible(5));
328     assertFalse(cs.isVisible(6));
329     assertFalse(cs.isVisible(7));
330   }
331
332   @Test(groups = { "Functional" })
333   public void testGetVisibleContigs()
334   {
335     ColumnSelection cs = new ColumnSelection();
336     cs.hideColumns(3, 6);
337     cs.hideColumns(8, 9);
338     cs.hideColumns(12, 12);
339
340     // start position is inclusive, end position exclusive:
341     int[] visible = cs.getVisibleContigs(1, 13);
342     assertEquals("[1, 2, 7, 7, 10, 11]", Arrays.toString(visible));
343
344     visible = cs.getVisibleContigs(4, 14);
345     assertEquals("[7, 7, 10, 11, 13, 13]", Arrays.toString(visible));
346
347     visible = cs.getVisibleContigs(3, 10);
348     assertEquals("[7, 7]", Arrays.toString(visible));
349
350     visible = cs.getVisibleContigs(4, 6);
351     assertEquals("[]", Arrays.toString(visible));
352   }
353
354   @Test(groups = { "Functional" })
355   public void testInvertColumnSelection()
356   {
357     ColumnSelection cs = new ColumnSelection();
358     cs.addElement(4);
359     cs.addElement(6);
360     cs.addElement(8);
361     cs.hideColumns(3, 3);
362     cs.hideColumns(6, 6);
363
364     // invert selection from start (inclusive) to end (exclusive)
365     // hidden columns are _not_ changed
366     cs.invertColumnSelection(2, 9);
367     assertEquals("[2, 5, 7]", cs.getSelected().toString());
368
369     cs.invertColumnSelection(1, 9);
370     assertEquals("[1, 4, 8]", cs.getSelected().toString());
371   }
372
373   @Test(groups = { "Functional" })
374   public void testMaxColumnSelection()
375   {
376     ColumnSelection cs = new ColumnSelection();
377     cs.addElement(0);
378     cs.addElement(513);
379     cs.addElement(1);
380     assertEquals(513, cs.getMax());
381     cs.removeElement(513);
382     assertEquals(1, cs.getMax());
383     cs.removeElement(1);
384     assertEquals(0, cs.getMax());
385     cs.addElement(512);
386     cs.addElement(513);
387     assertEquals(513, cs.getMax());
388
389   }
390
391   @Test(groups = { "Functional" })
392   public void testMinColumnSelection()
393   {
394     ColumnSelection cs = new ColumnSelection();
395     cs.addElement(0);
396     cs.addElement(513);
397     cs.addElement(1);
398     assertEquals(0, cs.getMin());
399     cs.removeElement(0);
400     assertEquals(1, cs.getMin());
401     cs.addElement(0);
402     assertEquals(0, cs.getMin());
403   }
404 }