2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.datamodel;
23 import java.util.List;
25 public class HiddenColumnsCursor
27 // absolute position of first hidden column
28 private int firstColumn;
30 // index of last visited region
31 private int regionIndex;
33 // number of hidden columns before last visited region
34 private int hiddenSoFar;
36 private List<int[]> hiddenColumns;
38 protected HiddenColumnsCursor()
44 * Set the cursor to a position
48 protected void resetCursor(List<int[]> hiddenCols)
52 hiddenColumns = hiddenCols;
53 if ((hiddenCols != null) && (!hiddenCols.isEmpty()))
55 firstColumn = hiddenColumns.get(0)[0];
63 * Delete the region the cursor is currently at. Avoids having to reset the
64 * cursor just because we deleted a region.
68 protected void updateForDeletedRegion(List<int[]> hiddenCols)
71 if ((hiddenCols != null) && (!hiddenCols.isEmpty()))
73 // if there is a region to the right of the current region,
74 // nothing changes; otherwise
75 // we deleted the last region (index=hiddenCols.size()-1)
76 // or the index was at the end of the alignment (index=hiddenCols.size())
77 if (regionIndex >= hiddenColumns.size() - 1)
79 // deleted last region, index is now end of alignment
80 regionIndex = hiddenCols.size();
84 hiddenColumns = hiddenCols;
87 protected void updateCursor(int index, int hiddenCount)
92 hiddenSoFar = hiddenCount;
96 protected synchronized int getIndex()
101 protected synchronized int getHiddenSoFar()
108 * Get the index of the region that column is within (if column is hidden) or
109 * which is to the right of column (if column is visible). If no hidden
110 * columns are to the right, will return size of hiddenColumns. If hidden
111 * columns is empty returns -1.
114 * absolute position of a column in the alignment
115 * @return region index
117 protected int findRegionForColumn(int column)
119 if (hiddenColumns == null)
124 int index = regionIndex;
125 int hiddenCount = hiddenSoFar;
127 if (index == hiddenColumns.size())
129 // went past the end of hiddenColumns collection last time
131 int[] region = hiddenColumns.get(index);
132 hiddenCount -= region[1] - region[0] + 1;
135 if ((hiddenColumns.get(index)[0] <= column)
136 && hiddenColumns.get(index)[1] >= column)
138 // column is in the current region
139 // we hit the jackpot
140 // don't need to move index
142 else if (column < firstColumn)
147 // column is after current region
148 else if (column > hiddenColumns.get(index)[1]) // includes if column >
151 // iterate from where we are now, if we're lucky we'll be close by
152 // (but still better than iterating from 0)
153 // stop when we find the region *before* column
154 // i.e. the next region starts after column or if not, ends after column
155 while ((index < hiddenColumns.size())
156 && (column > hiddenColumns.get(index)[1]))
158 int[] region = hiddenColumns.get(index);
159 hiddenCount += region[1] - region[0] + 1;
164 // column is before current region
165 else if (column < hiddenColumns.get(index)[0])
167 // column is before or in the previous region
168 if ((index > 0) && (hiddenColumns.get(index - 1)[1] >= column))
170 while ((index > 0) && (hiddenColumns.get(index)[1] > column))
173 int[] region = hiddenColumns.get(index);
174 hiddenCount -= region[1] - region[0] + 1;
178 updateCursor(index, hiddenCount);
183 * Get the number of hidden columns in regions before column i.e. excludes
184 * hidden columns in the region column is in, if any
187 * index of column in visible alignment
190 protected int getHiddenOffset(int column)
192 if (hiddenColumns == null)
197 int index = getIndex();
198 int hiddenCount = getHiddenSoFar();
200 if (column < firstColumn)
205 else if ((index < hiddenColumns.size())
206 && (hiddenColumns.get(index)[0] <= column + hiddenCount))
208 // iterate from where we are now, if we're lucky we'll be close by
209 // (but still better than iterating from 0)
210 while ((index < hiddenColumns.size())
211 && (hiddenColumns.get(index)[0] <= column + hiddenCount))
213 int[] region = hiddenColumns.get(index);
214 hiddenCount += region[1] - region[0] + 1;
221 && (hiddenColumns.get(index - 1)[1] >= column + hiddenCount))
224 int[] region = hiddenColumns.get(index);
225 hiddenCount -= region[1] - region[0] + 1;
229 updateCursor(index, hiddenCount);