JAL-2759 working first pass cursor
[jalview.git] / src / jalview / datamodel / HiddenColumnsCursor.java
1 package jalview.datamodel;
2
3 import java.util.List;
4
5 public class HiddenColumnsCursor
6 {
7   // absolute position of first hidden column
8   private int firstColumn;
9
10   // absolute position of last hidden column
11   private int lastColumn;
12
13   // index of last visited region
14   private int regionIndex;
15
16   // number of hidden columns before last visited region
17   private int hiddenSoFar;
18
19   private List<int[]> hiddenColumns;
20
21   protected HiddenColumnsCursor()
22   {
23
24   }
25
26   /**
27    * Set the cursor to a position
28    * 
29    * @param first
30    *          absolute position of first hidden column
31    * @param last
32    *          absolute position of last hidden column
33    * @param index
34    *          index of last visited region
35    * @param hiddenCount
36    *          number of hidden columns before last visited region
37    */
38   protected void resetCursor(List<int[]> hiddenCols)
39   {
40     synchronized (this)
41     {
42       if ((hiddenCols != null) && (!hiddenCols.isEmpty()))
43       {
44         hiddenColumns = hiddenCols;
45         firstColumn = hiddenColumns.get(0)[0];
46         lastColumn = hiddenColumns.get(hiddenColumns.size() - 1)[1];
47         regionIndex = 0;
48         hiddenSoFar = 0;
49       }
50     }
51   }
52
53   protected void updateCursor(int index, int hiddenCount)
54   {
55     synchronized (this)
56     {
57       regionIndex = index;
58       hiddenSoFar = hiddenCount;
59     }
60   }
61
62   private synchronized int getIndex()
63   {
64     return regionIndex;
65   }
66
67   private synchronized int getHiddenSoFar()
68   {
69     return hiddenSoFar;
70   }
71
72
73   /**
74    * Get the index of the region that column is within (if column is hidden) or
75    * which is to the right of column (if column is visible). If no hidden
76    * columns are to the right, will return size of hiddenColumns. If hidden
77    * columns is empty returns -1.
78    * 
79    * @param column
80    *          absolute position of a column in the alignment
81    * @return region index
82    */
83   protected int findRegionForColumn(int column)
84   {
85     if (hiddenColumns == null)
86     {
87       return -1;
88     }
89
90     int index = getIndex();
91     int hiddenCount = getHiddenSoFar();
92
93     if (index == hiddenColumns.size())
94     {
95       // went past the end of hiddenColumns collection last time
96       index--;
97       int[] region = hiddenColumns.get(index);
98       hiddenCount -= region[1] - region[0] + 1;
99     }
100
101     if ((hiddenColumns.get(index)[0] <= column)
102             && (hiddenColumns.get(index)[1] >= column))
103     {
104       // we hit the jackpot
105       // don't need to move index
106     }
107     else if (column < firstColumn)
108     {
109       index = 0;
110       hiddenCount = 0;
111     }
112     else if (column > lastColumn)
113     {
114       index = hiddenColumns.size();
115       // TODO resolve here - need full hidden count
116     }
117     else if (column > hiddenColumns.get(index)[1])
118     {
119       // iterate from where we are now, if we're lucky we'll be close by
120       // (but still better than iterating from 0)
121       while ((index < hiddenColumns.size())
122               && (hiddenColumns.get(index)[0] <= column))
123       {
124         int[] region = hiddenColumns.get(index);
125         hiddenCount += region[1] - region[0] + 1;
126         index++;
127       }
128
129     }
130     else // (column < hiddenColumns.get(regionIndex)[0])
131     {
132       while ((index > 0) && (hiddenColumns.get(index)[1] > column))
133       {
134         index--;
135         int[] region = hiddenColumns.get(index);
136         hiddenCount -= region[1] - region[0] + 1;
137       }
138     }
139     updateCursor(index, hiddenCount);
140     return index;
141   }
142
143   protected int getHiddenOffset(int column)
144   {
145     if (hiddenColumns == null)
146     {
147       return -1;
148     }
149
150     int index = getIndex();
151     int hiddenCount = getHiddenSoFar();
152
153     if (column < firstColumn)
154     {
155       index = 0;
156       hiddenCount = 0;
157     }
158     else if ((index < hiddenColumns.size())
159             && (hiddenColumns.get(index)[0] <= column + hiddenCount))
160     {
161       // iterate from where we are now, if we're lucky we'll be close by
162       // (but still better than iterating from 0)
163       while ((index < hiddenColumns.size())
164               && (hiddenColumns.get(index)[0] <= column + hiddenCount))
165       {
166         int[] region = hiddenColumns.get(index);
167         hiddenCount += region[1] - region[0] + 1;
168         index++;
169       }
170     }
171     else if (index < hiddenColumns.size())
172     {
173       while ((index > 0)
174               && (hiddenColumns.get(index)[1] > column + hiddenCount))
175       {
176         index--;
177         int[] region = hiddenColumns.get(index);
178         hiddenCount -= region[1] - region[0] + 1;
179       }
180
181     }
182     updateCursor(index, hiddenCount);
183     return hiddenCount;
184   }
185 }