Merge branch 'features/JAL-2388OverviewWindow' into develop
[jalview.git] / src / jalview / datamodel / ColumnSelection.java
index 98a7fe2..97bc5a3 100644 (file)
@@ -690,8 +690,8 @@ public class ColumnSelection
    * left-most visible column will always be returned.
    * 
    * @param hiddenColumn
-   *          int
-   * @return int
+   *          the column index in the full alignment including hidden columns
+   * @return the position of the column in the visible alignment
    */
   public int findColumnPosition(int hiddenColumn)
   {
@@ -708,15 +708,89 @@ public class ColumnSelection
           result -= region[1] + 1 - region[0];
         }
       } while ((hiddenColumn > region[1]) && (index < hiddenColumns.size()));
-      if (hiddenColumn > region[0] && hiddenColumn < region[1])
-      {
-        return region[0] + hiddenColumn - result;
+
+      if (hiddenColumn >= region[0] && hiddenColumn <= region[1])
+       {
+         // Here the hidden column is within a region, so
+         // we want to return the position of region[0]-1, adjusted for any
+         // earlier hidden columns.
+         // Calculate the difference between the actual hidden col position
+         // and region[0]-1, and then subtract from result to convert result from
+         // the adjusted hiddenColumn value to the adjusted region[0]-1 value
+
+        // However, if the region begins at 0 we cannot return region[0]-1
+        // just return 0
+        if (region[0] == 0)
+        {
+          return 0;
+        }
+        else
+        {
+          return result - (hiddenColumn - region[0] + 1);
+        }
       }
     }
     return result; // return the shifted position after removing hidden columns.
   }
 
   /**
+   * Find the visible column which is a given visible number of columns to the
+   * left of another visible column. i.e. for a startColumn x, the column which
+   * is distance 1 away will be column x-1.
+   * 
+   * @param visibleDistance
+   *          the number of visible columns to offset by
+   * @param startColumn
+   *          the column to start from
+   * @return the position of the column in the visible alignment
+   */
+  public int subtractVisibleColumns(int visibleDistance, int startColumn)
+  {
+    int distance = visibleDistance;
+
+    // in case startColumn is in a hidden region, move it to the left
+    int start = adjustForHiddenColumns(findColumnPosition(startColumn));
+
+    // get index of hidden region to left of start
+    int index = getHiddenIndexLeft(start);
+    if (index == -1)
+    {
+      // no hidden regions to left of startColumn
+      return start - distance;
+    }
+
+    // walk backwards through the alignment subtracting the counts of visible
+    // columns from distance
+    int[] region;
+    int gap = 0;
+    int nextstart = start;
+
+    while ((index > -1) && (distance - gap > 0))
+    {
+      // subtract the gap to right of region from distance
+      distance -= gap;
+      start = nextstart;
+
+      // calculate the next gap
+      region = hiddenColumns.get(index);
+      gap = start - region[1];
+
+      // set start to just to left of current region
+      nextstart = region[0] - 1;
+      index--;
+    }
+
+    if (distance - gap > 0)
+    {
+      // fell out of loop because there are no more hidden regions
+      distance -= gap;
+      return nextstart - distance;
+    }
+    return start - distance;
+
+  }
+
+  /**
    * Use this method to determine where the next hiddenRegion starts
    * 
    * @param hiddenRegion
@@ -805,6 +879,35 @@ public class ColumnSelection
 
   }
 
+  /**
+   * This method returns the index of the hidden region to the left of a column
+   * position. If the column is in a hidden region it returns the index of the
+   * region to the left. If there is no hidden region to the left it returns -1.
+   * 
+   * @param pos
+   *          int
+   */
+  private int getHiddenIndexLeft(int pos)
+  {
+    if (hiddenColumns != null)
+    {
+      int index = hiddenColumns.size() - 1;
+      do
+      {
+        int[] region = hiddenColumns.elementAt(index);
+        if (pos > region[1])
+        {
+          return index;
+        }
+
+        index--;
+      } while (index > -1);
+    }
+
+    return -1;
+
+  }
+
   public void hideSelectedColumns()
   {
     synchronized (selection)