Merge branch 'develop' into bug/JAL-2510amendFeatures
[jalview.git] / src / jalview / datamodel / VisibleColsIterator.java
diff --git a/src/jalview/datamodel/VisibleColsIterator.java b/src/jalview/datamodel/VisibleColsIterator.java
new file mode 100644 (file)
index 0000000..70de1e3
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all visible columns in an alignment
+ * 
+ * @author kmourao
+ *
+ */
+public class VisibleColsIterator implements Iterator<Integer>
+{
+  private int last;
+
+  private int current;
+
+  private int next;
+
+  private List<int[]> hidden;
+
+  private int lasthiddenregion;
+
+  public VisibleColsIterator(int firstcol, int lastcol,
+          HiddenColumns hiddenCols)
+  {
+    last = lastcol;
+    current = firstcol;
+    next = firstcol;
+    hidden = hiddenCols.getHiddenRegions();
+    lasthiddenregion = -1;
+
+    if (hidden != null)
+    {
+      int i = 0;
+      for (i = 0; i < hidden.size(); ++i)
+      {
+        if (current >= hidden.get(i)[0] && current <= hidden.get(i)[1])
+        {
+          // current is hidden, move to right
+          current = hidden.get(i)[1] + 1;
+          next = current;
+        }
+        if (current < hidden.get(i)[0])
+        {
+          break;
+        }
+      }
+      lasthiddenregion = i - 1;
+
+      for (i = hidden.size() - 1; i >= 0; --i)
+      {
+        if (last >= hidden.get(i)[0] && last <= hidden.get(i)[1])
+        {
+          // last is hidden, move to left
+          last = hidden.get(i)[0] - 1;
+        }
+        if (last > hidden.get(i)[1])
+        {
+          break;
+        }
+      }
+    }
+  }
+
+  @Override
+  public boolean hasNext()
+  {
+    return next <= last;
+  }
+
+  @Override
+  public Integer next()
+  {
+    if (next > last)
+    {
+      throw new NoSuchElementException();
+    }
+    current = next;
+    if ((hidden != null) && (lasthiddenregion + 1 < hidden.size()))
+    {
+      // still some more hidden regions
+      if (next + 1 < hidden.get(lasthiddenregion + 1)[0])
+      {
+        // next+1 is still before the next hidden region
+        next++;
+      }
+      else if ((next + 1 >= hidden.get(lasthiddenregion + 1)[0])
+              && (next + 1 <= hidden.get(lasthiddenregion + 1)[1]))
+      {
+        // next + 1 is in the next hidden region
+        next = hidden.get(lasthiddenregion + 1)[1] + 1;
+        lasthiddenregion++;
+      }
+    }
+    else
+    {
+      // finished with hidden regions, just increment normally
+      next++;
+    }
+    return current;
+  }
+
+  @Override
+  public void remove()
+  {
+    throw new UnsupportedOperationException();
+  }
+}
+