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.ArrayList;
24 import java.util.List;
26 public class HiddenColumnsCursor
28 // absolute position of first hidden column
29 private int firstColumn;
31 private List<int[]> hiddenColumns = new ArrayList<>();
33 private HiddenCursorPosition cursorPos = new HiddenCursorPosition(0, 0);
35 protected HiddenColumnsCursor()
40 protected HiddenColumnsCursor(List<int[]> hiddenCols)
42 resetCursor(hiddenCols, 0, 0);
45 protected HiddenColumnsCursor(List<int[]> hiddenCols, int index,
48 resetCursor(hiddenCols, index, hiddencount);
52 * Reset the cursor with a new hidden columns collection, where we know in
53 * advance the index and hidden columns count of a particular location.
56 * new hidden columns collection
58 * cursor index to reset to
60 * hidden columns count to reset to
62 private void resetCursor(List<int[]> hiddenCols, int index,
65 hiddenColumns = hiddenCols;
66 if (!hiddenCols.isEmpty())
68 firstColumn = hiddenColumns.get(0)[0];
69 cursorPos = new HiddenCursorPosition(index,
75 * Delete the region the cursor is currently at. Avoids having to reset the
76 * cursor just because we deleted a region.
78 * Calls to updateForDeletedRegion should be made from within a writeLock in
79 * the HiddenColumns class - since changes to the hiddenColumns collection
80 * require a writeLock the lock should already exist.
84 protected void updateForDeletedRegion(List<int[]> hiddenCols)
87 if (!hiddenCols.isEmpty())
89 // if there is a region to the right of the current region,
90 // nothing changes; otherwise
91 // we deleted the last region (index=hiddenCols.size()-1)
92 // or the index was at the end of the alignment (index=hiddenCols.size())
93 HiddenCursorPosition oldpos = cursorPos;
95 int index = oldpos.getRegionIndex();
96 if (index >= hiddenColumns.size() - 1)
98 // deleted last region, index is now end of alignment
99 index = hiddenCols.size();
101 cursorPos = new HiddenCursorPosition(index,
102 oldpos.getHiddenSoFar());
105 hiddenColumns = hiddenCols;
109 * Get the cursor pointing to the hidden region that column is within (if
110 * column is hidden) or which is to the right of column (if column is
111 * visible). If no hidden columns are to the right, returns a cursor pointing
112 * to an imaginary hidden region beyond the end of the hidden columns
113 * collection (this ensures the count of previous hidden columns is correct).
114 * If hidden columns is empty returns null.
117 * absolute position of a column in the alignment
118 * @return cursor pointing to hidden region containing the column (if hidden)
119 * or to the right of the column (if visible)
121 /*protected HiddenCursorPosition findRegionForColumn(int column)
123 return findRegionForColumn(column, false);
127 * Get the cursor pointing to the hidden region just after a visible column
130 * index of column in *visible* alignment (therefore by definition
132 * @return cursor pointing to hidden region to the right of the column
134 /* protected HiddenCursorPosition findRegionForVisColumn(int column)
136 return findRegionForColumn(column, true);
140 * Get the cursor pointing to the hidden region that column is within (if
141 * column is hidden) or which is to the right of column (if column is
142 * visible). If no hidden columns are to the right, returns a cursor pointing
143 * to an imaginary hidden region beyond the end of the hidden columns
144 * collection (this ensures the count of previous hidden columns is correct).
145 * If hidden columns is empty returns null.
148 * index of column in visible or absolute coordinates
150 * true if column is in visible coordinates, false if absolute
151 * @return cursor pointing to hidden region containing the column (if hidden)
152 * or to the right of the column (if visible)
154 protected HiddenCursorPosition findRegionForColumn(int column,
157 if (hiddenColumns.isEmpty())
162 // used to add in hiddenColumns offset when working with visible columns
163 int offset = (useVisible ? 1 : 0);
165 HiddenCursorPosition oldpos = cursorPos;
166 int index = oldpos.getRegionIndex();
167 int hiddenCount = oldpos.getHiddenSoFar();
169 if (column < firstColumn)
175 // column is after current region
176 else if ((index < hiddenColumns.size())
177 && (hiddenColumns.get(index)[0] <= column
178 + offset * hiddenCount))
180 // iterate from where we are now, if we're lucky we'll be close by
181 // (but still better than iterating from 0)
182 // stop when we find the region *before* column
183 // i.e. the next region starts after column or if not, ends after column
184 while ((index < hiddenColumns.size())
185 && (((useVisible && hiddenColumns.get(index)[0] <= column
186 + offset * hiddenCount))
188 && hiddenColumns.get(index)[1] < column)))
190 int[] region = hiddenColumns.get(index);
191 hiddenCount += region[1] - region[0] + 1;
196 // column is before current region
199 // column is before or in the previous region
200 while ((index > 0) && (hiddenColumns.get(index - 1)[1] >= column
201 + offset * hiddenCount))
204 int[] region = hiddenColumns.get(index);
205 hiddenCount -= region[1] - region[0] + 1;
209 if (index != oldpos.getRegionIndex()
210 || hiddenCount != oldpos.getHiddenSoFar())
212 return new HiddenCursorPosition(index, hiddenCount);