JAL-2759 setup hideBitSet over range for hideInsertions
authorkiramt <k.mourao@dundee.ac.uk>
Tue, 16 Jan 2018 15:45:59 +0000 (15:45 +0000)
committerkiramt <k.mourao@dundee.ac.uk>
Tue, 16 Jan 2018 15:45:59 +0000 (15:45 +0000)
src/jalview/datamodel/HiddenColsIterator.java
src/jalview/datamodel/HiddenColumns.java
src/jalview/gui/PopupMenu.java
test/jalview/gui/PopupMenuTest.java

index 55a3d8b..0084912 100644 (file)
@@ -102,4 +102,10 @@ public class HiddenColsIterator implements Iterator<int[]>
     currentPosition++;
     return currentRegion;
   }
+
+  @Override
+  public void remove()
+  {
+    localHidden.remove(--currentPosition);
+  }
 }
index 49f82f5..037afc4 100644 (file)
@@ -1121,7 +1121,7 @@ public class HiddenColumns
    * Hide columns corresponding to the marked bits
    * 
    * @param inserts
-   *          - columns map to bits starting from zero
+   *          - columns mapped to bits starting from zero
    */
   public void hideColumns(BitSet inserts)
   {
@@ -1144,6 +1144,85 @@ public class HiddenColumns
   }
 
   /**
+   * Hide columns corresponding to the marked bits, within the range
+   * [start,end]. Entries in tohide which are outside [start,end] are ignored.
+   * 
+   * @param tohide
+   *          columns mapped to bits starting from zero
+   * @param start
+   *          start of range to hide columns within
+   * @param end
+   *          end of range to hide columns within
+   */
+  public void hideColumns(BitSet tohide, int start, int end)
+  {
+    clearHiddenColumnsInRange(start, end);
+
+    // make sure only bits between start and end are set
+    tohide.clear(0, start - 1);
+    tohide.clear(Math.min(end + 1, tohide.length() - 1),
+            tohide.length() - 1);
+
+    hideColumns(tohide);
+  }
+
+  /**
+   * Make all columns in the range [start,end] visible
+   * 
+   * @param start
+   *          start of range to show columns
+   * @param end
+   *          end of range to show columns
+   */
+  private void clearHiddenColumnsInRange(int start, int end)
+  {
+    try
+    {
+      LOCK.writeLock().lock();
+      
+      HiddenCursorPosition pos = cursor.findRegionForColumn(start);
+      int index = pos.getRegionIndex();
+      int startindex = index; // first index in hiddenColumns to remove
+      
+      if (index != -1 && index != hiddenColumns.size())
+      {
+        // regionIndex is the region which either contains start
+        // or lies to the right of start
+        int[] region = hiddenColumns.get(index);
+        if (region[0] < start && region[1] >= start)
+        {
+          // region contains start, truncate so that it ends just before start
+          region[1] = start - 1;
+          startindex++;
+        }
+      }
+      
+      pos = cursor.findRegionForColumn(end);
+      index = pos.getRegionIndex();
+      int endindex = index - 1; // last index in hiddenColumns to remove
+
+      if (index != -1 && index != hiddenColumns.size())
+      {
+        // regionIndex is the region which either contains end
+        // or lies to the right of end
+        int[] region = hiddenColumns.get(index);
+        if (region[0] <= end && region[1] > end)
+        {
+          // region contains end, truncate so that it starts just after end
+          region[0] = end + 1;
+        }
+      }
+      
+      hiddenColumns.subList(startindex, endindex + 1).clear();
+      cursor.resetCursor(hiddenColumns);
+      numColumns = 0;
+    } finally
+    {
+      LOCK.writeLock().unlock();
+    }
+  }
+
+  /**
    * 
    * @param inserts
    *          BitSet where hidden columns will be marked
index 1e4116d..9bc2ca1 100644 (file)
@@ -1453,15 +1453,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
   protected void hideInsertions_actionPerformed(ActionEvent actionEvent)
   {
-
-    HiddenColumns hidden = new HiddenColumns();
-    BitSet inserts = new BitSet(), mask = new BitSet();
-
-    // set mask to preserve existing hidden columns outside selected group
-    if (ap.av.hasHiddenColumns())
-    {
-      ap.av.getAlignment().getHiddenColumns().markHiddenRegions(mask);
-    }
+    HiddenColumns hidden = ap.av.getAlignment().getHiddenColumns();
+    BitSet inserts = new BitSet();
 
     boolean markedPopup = false;
     // mark inserts in current selection
@@ -1469,10 +1462,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     {
       // mark just the columns in the selection group to be hidden
       inserts.set(ap.av.getSelectionGroup().getStartRes(),
-              ap.av.getSelectionGroup().getEndRes() + 1);
-
-      // and clear that part of the mask
-      mask.andNot(inserts);
+              ap.av.getSelectionGroup().getEndRes() + 1); // TODO why +1?
 
       // now clear columns without gaps
       for (SequenceI sq : ap.av.getSelectionGroup().getSequences())
@@ -1483,29 +1473,18 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         }
         inserts.and(sq.getInsertionsAsBits());
       }
-    }
-    else
-    {
-      // initially, mark all columns to be hidden
-      inserts.set(0, ap.av.getAlignment().getWidth());
-
-      // and clear out old hidden regions completely
-      mask.clear();
+      hidden.hideColumns(inserts, ap.av.getSelectionGroup().getStartRes(),
+              ap.av.getSelectionGroup().getEndRes());
     }
 
     // now mark for sequence under popup if we haven't already done it
-    if (!markedPopup && sequence != null)
+    else if (!markedPopup && sequence != null)
     {
-      inserts.and(sequence.getInsertionsAsBits());
-    }
+      inserts.or(sequence.getInsertionsAsBits());
 
-    // finally, preserve hidden regions outside selection
-    inserts.or(mask);
-
-    // and set hidden columns accordingly
-    hidden.hideColumns(inserts);
-
-    ap.av.getAlignment().setHiddenColumns(hidden);
+      // and set hidden columns accordingly
+      hidden.hideColumns(inserts);
+    }
     refresh();
   }
 
index 7e077d0..8f60021 100644 (file)
@@ -573,14 +573,8 @@ public class PopupMenuTest
     // get sequences from the alignment
     List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
     
-    // get the Popup Menu for first sequence - no insertions
-    testee = new PopupMenu(parentPanel, (Sequence) seqs.get(0), null);
-    testee.hideInsertions_actionPerformed(null);
-    
-    HiddenColumns hidden = parentPanel.av.getAlignment().getHiddenColumns();
-    Iterator<int[]> it = hidden.iterator();
-    assertFalse(it.hasNext());
-
+    // add our own seqs to avoid problems with changes to existing sequences
+    // (gap at end of sequences varies depending on how tests are run!)
     Sequence seqGap1 = new Sequence("GappySeq",
             "AAAA----AA-AAAAAAA---AAA-----------AAAAAAAAAA--");
     seqGap1.createDatasetSequence();
@@ -589,10 +583,26 @@ public class PopupMenuTest
             "AAAAAA-AAAAA---AAA--AAAAA--AAAAAAA-AAAAAA");
     seqGap2.createDatasetSequence();
     seqs.add(seqGap2);
-    Sequence seqGap3 = new Sequence("OneGapSeq",
+    Sequence seqGap3 = new Sequence("AnotherGapSeq",
             "AAAAAA-AAAAAA--AAAAAA-AAAAAAAAAAA---AAAAAAAA");
     seqGap3.createDatasetSequence();
     seqs.add(seqGap3);
+    Sequence seqGap4 = new Sequence("NoGaps",
+            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+    seqGap4.createDatasetSequence();
+    seqs.add(seqGap4);
+
+    ColumnSelection sel = new ColumnSelection();
+    parentPanel.av.getAlignment().getHiddenColumns()
+            .revealAllHiddenColumns(sel);
+
+    // get the Popup Menu for 7th sequence - no insertions
+    testee = new PopupMenu(parentPanel, (Sequence) seqs.get(7), null);
+    testee.hideInsertions_actionPerformed(null);
+    
+    HiddenColumns hidden = parentPanel.av.getAlignment().getHiddenColumns();
+    Iterator<int[]> it = hidden.iterator();
+    assertFalse(it.hasNext());
 
     // get the Popup Menu for GappySeq - this time we have insertions
     testee = new PopupMenu(parentPanel, (Sequence) seqs.get(4), null);
@@ -627,7 +637,7 @@ public class PopupMenuTest
 
     assertFalse(it.hasNext());
 
-    ColumnSelection sel = new ColumnSelection();
+    sel = new ColumnSelection();
     hidden.revealAllHiddenColumns(sel);
 
     // make a sequence group and hide insertions within the group