* require a writeLock the lock should already exist.
*
* @param hiddenCols
+ * replacement list of hidden column regions
+ * @param remove
+ * number of columns which were deleted
*/
- protected void updateForDeletedRegion(List<int[]> hiddenCols)
+ protected void updateForDeletedRegion(List<int[]> hiddenCols, int remove)
{
-
+ hiddenColumns = hiddenCols;
if (!hiddenCols.isEmpty())
{
- // if there is a region to the right of the current region,
- // nothing changes; otherwise
- // we deleted the last region (index=hiddenCols.size()-1)
- // or the index was at the end of the alignment (index=hiddenCols.size())
- HiddenCursorPosition oldpos = cursorPos;
-
- int index = oldpos.getRegionIndex();
- if (index >= hiddenColumns.size() - 1)
+ if (cursorPos.getRegionIndex() >= hiddenCols.size())
{
- // deleted last region, index is now end of alignment
- index = hiddenCols.size();
-
- cursorPos = new HiddenCursorPosition(index,
- oldpos.getHiddenSoFar());
+ cursorPos = new HiddenCursorPosition(hiddenCols.size(),
+ cursorPos.getHiddenSoFar() - remove);
}
}
- hiddenColumns = hiddenCols;
}
/**
* If hidden columns is empty returns null.
*
* @param column
- * absolute position of a column in the alignment
- * @return cursor pointing to hidden region containing the column (if hidden)
- * or to the right of the column (if visible)
- */
- /*protected HiddenCursorPosition findRegionForColumn(int column)
- {
- return findRegionForColumn(column, false);
- }*/
-
- /**
- * Get the cursor pointing to the hidden region just after a visible column
- *
- * @param column
- * index of column in *visible* alignment (therefore by definition
- * column is visible)
- * @return cursor pointing to hidden region to the right of the column
- */
- /* protected HiddenCursorPosition findRegionForVisColumn(int column)
- {
- return findRegionForColumn(column, true);
- }*/
-
- /**
- * Get the cursor pointing to the hidden region that column is within (if
- * column is hidden) or which is to the right of column (if column is
- * visible). If no hidden columns are to the right, returns a cursor pointing
- * to an imaginary hidden region beyond the end of the hidden columns
- * collection (this ensures the count of previous hidden columns is correct).
- * If hidden columns is empty returns null.
- *
- * @param column
* index of column in visible or absolute coordinates
* @param useVisible
* true if column is in visible coordinates, false if absolute
// used to add in hiddenColumns offset when working with visible columns
int offset = (useVisible ? 1 : 0);
- HiddenCursorPosition oldpos = cursorPos;
- int index = oldpos.getRegionIndex();
- int hiddenCount = oldpos.getHiddenSoFar();
+ HiddenCursorPosition pos = cursorPos;
+ int index = pos.getRegionIndex();
+ int hiddenCount = pos.getHiddenSoFar();
if (column < firstColumn)
{
- index = 0;
- hiddenCount = 0;
+ pos = new HiddenCursorPosition(0, 0);
}
// column is after current region
// (but still better than iterating from 0)
// stop when we find the region *before* column
// i.e. the next region starts after column or if not, ends after column
- while ((index < hiddenColumns.size())
- && (((useVisible && hiddenColumns.get(index)[0] <= column
- + offset * hiddenCount))
- || (!useVisible
- && hiddenColumns.get(index)[1] < column)))
- {
- int[] region = hiddenColumns.get(index);
- hiddenCount += region[1] - region[0] + 1;
- index++;
- }
+ pos = searchForward(pos, column, useVisible);
}
// column is before current region
else
{
- // column is before or in the previous region
- while ((index > 0) && (hiddenColumns.get(index - 1)[1] >= column
- + offset * hiddenCount))
+ pos = searchBackward(pos, column, useVisible);
+ }
+ cursorPos = pos;
+ return pos;
+ }
+
+ /**
+ * Search forwards through the hidden columns collection to find the hidden
+ * region immediately before a column
+ *
+ * @param pos
+ * current position
+ * @param column
+ * column to locate
+ * @param useVisible
+ * whether using visible or absolute coordinates
+ * @return position of region before column
+ */
+ private HiddenCursorPosition searchForward(HiddenCursorPosition pos,
+ int column, boolean useVisible)
+ {
+ HiddenCursorPosition p = pos;
+ if (useVisible)
+ {
+ while ((p.getRegionIndex() < hiddenColumns.size())
+ && hiddenColumns.get(p.getRegionIndex())[0] <= column
+ + p.getHiddenSoFar())
{
- index--;
- int[] region = hiddenColumns.get(index);
- hiddenCount -= region[1] - region[0] + 1;
+ p = stepForward(p);
}
}
+ else
+ {
+ while ((p.getRegionIndex() < hiddenColumns.size())
+ && hiddenColumns.get(p.getRegionIndex())[1] < column)
+ {
+ p = stepForward(p);
+ }
+ }
+ return p;
+ }
+
+ /**
+ * Move to the next (rightwards) hidden region after a given cursor position
+ *
+ * @param p
+ * current position of cursor
+ * @return new position of cursor at next region
+ */
+ private HiddenCursorPosition stepForward(HiddenCursorPosition p)
+ {
+ int[] region = hiddenColumns.get(p.getRegionIndex());
+
+ // increment the index, and add this region's hidden columns to the hidden
+ // column count
+ return new HiddenCursorPosition(p.getRegionIndex() + 1,
+ p.getHiddenSoFar() + region[1] - region[0] + 1);
+ }
+
+ /**
+ * Search backwards through the hidden columns collection to find the hidden
+ * region immediately before (left of) a given column
+ *
+ * @param pos
+ * current position
+ * @param column
+ * column to locate
+ * @param useVisible
+ * whether using visible or absolute coordinates
+ * @return position of region immediately to left of column
+ */
+ private HiddenCursorPosition searchBackward(HiddenCursorPosition p,
+ int column, boolean useVisible)
+ {
+ int i = p.getRegionIndex();
+ int h = p.getHiddenSoFar();
+
+ // used to add in hiddenColumns offset when working with visible columns
+ int offset = (useVisible ? 1 : 0);
- if (index != oldpos.getRegionIndex()
- || hiddenCount != oldpos.getHiddenSoFar())
+ while ((i > 0) && (hiddenColumns.get(i - 1)[1] >= column + offset * h))
{
- return new HiddenCursorPosition(index, hiddenCount);
+ i--;
+ int[] region = hiddenColumns.get(i);
+ h -= region[1] - region[0] + 1;
}
- return oldpos;
+ return new HiddenCursorPosition(i, h);
}
}
public class HiddenColumnsCursorTest
{
+
+ @Test(groups = { "Functional" })
+ public void testConstructor()
+ {
+ HiddenColumnsCursor cursor = new HiddenColumnsCursor();
+ assertNull(cursor.findRegionForColumn(0, false));
+
+ List<int[]> hlist = new ArrayList<>();
+ cursor = new HiddenColumnsCursor(hlist);
+ assertNull(cursor.findRegionForColumn(0, false));
+
+ cursor = new HiddenColumnsCursor(hlist, 3, 12);
+ assertNull(cursor.findRegionForColumn(0, false));
+
+ hlist.add(new int[] { 3, 7 });
+ hlist.add(new int[] { 15, 25 });
+ cursor = new HiddenColumnsCursor(hlist);
+ HiddenCursorPosition p = cursor.findRegionForColumn(8, false);
+ assertEquals(1, p.getRegionIndex());
+
+ cursor = new HiddenColumnsCursor(hlist, 1, 5);
+ p = cursor.findRegionForColumn(8, false);
+ assertEquals(1, p.getRegionIndex());
+ }
+
/**
* Test the method which finds the corresponding region given a column
*/
* Test the method which counts the number of hidden columns before a column
*/
@Test(groups = { "Functional" })
- public void testGetHiddenOffset()
+ public void testFindRegionForColumn_Visible()
{
HiddenColumnsCursor cursor = new HiddenColumnsCursor();
assertEquals(46, offset);
}
+ /**
+ * Test the method which updates for a deleted region
+ */
+ @Test(groups = { "Functional" })
+ public void testUpdateForDeletedRegion()
+ {
+ List<int[]> hlist = new ArrayList<>();
+ HiddenColumnsCursor cursor = new HiddenColumnsCursor(hlist, 1, 5);
+ cursor.updateForDeletedRegion(hlist, 0);
+ assertNull(cursor.findRegionForColumn(30, false));
+
+ hlist.add(new int[] { 3, 7 });
+ hlist.add(new int[] { 15, 25 });
+
+ cursor = new HiddenColumnsCursor(hlist, 1, 5);
+
+ HiddenCursorPosition p = cursor.findRegionForColumn(30, false);
+ assertEquals(16, p.getHiddenSoFar());
+
+ List<int[]> hlist2 = new ArrayList<>();
+ hlist2.add(new int[] { 3, 7 });
+ cursor.updateForDeletedRegion(hlist2, 11);
+ p = cursor.findRegionForColumn(30, false);
+ assertEquals(5, p.getHiddenSoFar());
+ }
+
}