Merge branch 'feature/JAL-2611' into develop
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 1 Aug 2017 09:55:35 +0000 (11:55 +0200)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 1 Aug 2017 09:55:35 +0000 (11:55 +0200)
16 files changed:
examples/exampleFeatures.txt
help/html/features/AnnotationColumnSelectionWithSM.gif [deleted file]
help/html/features/AnnotationColumnSelectionWithSM.png [new file with mode: 0644]
help/html/features/columnFilterByAnnotation.html
src/jalview/appletgui/FeatureColourChooser.java
src/jalview/appletgui/FeatureSettings.java
src/jalview/appletgui/PaintRefresher.java
src/jalview/appletgui/SeqPanel.java
src/jalview/gui/FeatureColourChooser.java
src/jalview/gui/IdPanel.java
src/jalview/gui/SeqPanel.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
test/jalview/io/FeaturesFileTest.java
test/jalview/renderer/seqfeatures/FeatureColourFinderTest.java
test/jalview/viewmodel/OverviewDimensionsShowHiddenTest.java

index 83dc4b1..cc159d1 100755 (executable)
@@ -1,5 +1,5 @@
-ST-TURN-IIL    blue|255,0,255|absolute|20.0|95.0|below|66.0
-GAMMA-TURN-CLASSIC     lightGray|0,255,255|20.0|95.0|below|66.0
+ST-TURN-IIL    blue
+GAMMA-TURN-CLASSIC     lightGray
 BETA-TURN-IR   9a6a94
 BETA-TURN-IL   d6a6ca
 BETA-BULGE     1dc451
@@ -24,6 +24,7 @@ BETA-TURN-IIR c79792
 PHOSPHORYLATION (T)    c88395
 BETA-TURN-IIL  8b5b50
 ST-MOTIF       ac25a1
+kdHydrophobicity       ccffcc|333300|-3.9|4.5|above|-2.0
 
 STARTGROUP     uniprot
 <html><a href="http://pfam.xfam.org/family/PF00111">Pfam family</a></html>     FER_CAPAA       -1      0       0       Pfam
@@ -310,3 +311,54 @@ NEST-RL    FER1_MAIZE      -1      124     126     NEST-RL
 NEST-RL        FER1_MAIZE      -1      241     243     NEST-RL
 NEST-RL        FER1_MAIZE      -1      292     294     NEST-RL
 ENDGROUP       s3dm
+
+STARTGROUP     kd
+A      Q93XJ9_SOLTU    -1      48      48      kdHydrophobicity        1.8
+A      Q93XJ9_SOLTU    -1      49      49      kdHydrophobicity        -0.8
+A      Q93XJ9_SOLTU    -1      50      50      kdHydrophobicity        -1.3
+A      Q93XJ9_SOLTU    -1      51      51      kdHydrophobicity        -3.9
+A      Q93XJ9_SOLTU    -1      52      52      kdHydrophobicity        4.2
+A      Q93XJ9_SOLTU    -1      53      53      kdHydrophobicity        -3.9
+A      Q93XJ9_SOLTU    -1      54      54      kdHydrophobicity        3.8
+A      Q93XJ9_SOLTU    -1      55      55      kdHydrophobicity        4.5
+A      Q93XJ9_SOLTU    -1      56      56      kdHydrophobicity        -0.7
+A      Q93XJ9_SOLTU    -1      57      57      kdHydrophobicity        -1.6
+A      Q93XJ9_SOLTU    -1      58      58      kdHydrophobicity        -3.5
+A      Q93XJ9_SOLTU    -1      59      59      kdHydrophobicity        -0.4
+A      Q93XJ9_SOLTU    -1      60      60      kdHydrophobicity        -1.6
+A      Q93XJ9_SOLTU    -1      61      61      kdHydrophobicity        4.5
+A      Q93XJ9_SOLTU    -1      62      62      kdHydrophobicity        -3.5
+A      Q93XJ9_SOLTU    -1      63      63      kdHydrophobicity        2.8
+A      FER1_SPIOL      -1      51      51      kdHydrophobicity        1.8
+A      FER1_SPIOL      -1      52      52      kdHydrophobicity        1.8
+A      FER1_SPIOL      -1      53      53      kdHydrophobicity        -1.3
+A      FER1_SPIOL      -1      54      54      kdHydrophobicity        -3.9
+A      FER1_SPIOL      -1      55      55      kdHydrophobicity        4.2
+A      FER1_SPIOL      -1      56      56      kdHydrophobicity        -0.7
+A      FER1_SPIOL      -1      57      57      kdHydrophobicity        3.8
+A      FER1_SPIOL      -1      58      58      kdHydrophobicity        4.2
+A      FER1_SPIOL      -1      59      59      kdHydrophobicity        -0.7
+A      FER1_SPIOL      -1      60      60      kdHydrophobicity        -1.6
+A      FER1_SPIOL      -1      61      61      kdHydrophobicity        -0.7
+A      FER1_SPIOL      -1      62      62      kdHydrophobicity        -0.4
+A      FER1_SPIOL      -1      63      63      kdHydrophobicity        -3.5
+A      FER1_SPIOL      -1      64      64      kdHydrophobicity        4.2
+A      FER1_SPIOL      -1      65      65      kdHydrophobicity        -3.5
+A      FER1_SPIOL      -1      66      66      kdHydrophobicity        2.8
+C      FER1_MAIZE      -1      53      53      kdHydrophobicity        1.8
+C      FER1_MAIZE      -1      54      54      kdHydrophobicity        -0.7
+C      FER1_MAIZE      -1      55      55      kdHydrophobicity        -1.3
+C      FER1_MAIZE      -1      56      56      kdHydrophobicity        -3.5
+C      FER1_MAIZE      -1      57      57      kdHydrophobicity        4.2
+C      FER1_MAIZE      -1      58      58      kdHydrophobicity        -3.9
+C      FER1_MAIZE      -1      59      59      kdHydrophobicity        3.8
+C      FER1_MAIZE      -1      60      60      kdHydrophobicity        4.5
+C      FER1_MAIZE      -1      61      61      kdHydrophobicity        -0.7
+C      FER1_MAIZE      -1      62      62      kdHydrophobicity        -1.6
+C      FER1_MAIZE      -1      63      63      kdHydrophobicity        -3.5
+C      FER1_MAIZE      -1      64      64      kdHydrophobicity        -0.4
+C      FER1_MAIZE      -1      65      65      kdHydrophobicity        -3.5
+C      FER1_MAIZE      -1      66      66      kdHydrophobicity        4.2
+C      FER1_MAIZE      -1      67      67      kdHydrophobicity        -3.5
+C      FER1_MAIZE      -1      68      68      kdHydrophobicity        3.8
+ENDGROUP       kd
diff --git a/help/html/features/AnnotationColumnSelectionWithSM.gif b/help/html/features/AnnotationColumnSelectionWithSM.gif
deleted file mode 100644 (file)
index 4373493..0000000
Binary files a/help/html/features/AnnotationColumnSelectionWithSM.gif and /dev/null differ
diff --git a/help/html/features/AnnotationColumnSelectionWithSM.png b/help/html/features/AnnotationColumnSelectionWithSM.png
new file mode 100644 (file)
index 0000000..c86c5b8
Binary files /dev/null and b/help/html/features/AnnotationColumnSelectionWithSM.png differ
index b260cee..2651a10 100644 (file)
@@ -37,7 +37,7 @@
   </p>
   <table>
     <tr>
-      <td><img src="AnnotationColumnSelectionWithSM.gif"></td>
+      <td><img src="AnnotationColumnSelectionWithSM.png"></td>
       <td><img src="AnnotationColumnSelectionWithoutSM.gif"></td>
     </tr>
   </table>
@@ -76,7 +76,9 @@
         <li>Select whether to filter the alignment above or below
           the threshold.</li>
         <li>Change the threshold value with the slider, or enter it
-          in the text box.</li>
+          in the text box.
+       <li>The <em>As Percentage</em> checkbox allows thresholds to
+          be set as a percentage rather than absolute value.</li>
       </ul>
     <li><strong>Actions</strong>
       <ul>
index 0e85017..72fa982 100644 (file)
@@ -46,58 +46,90 @@ import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
-import java.util.Hashtable;
 
 public class FeatureColourChooser extends Panel implements ActionListener,
         AdjustmentListener, ItemListener, MouseListener
 {
-  JVDialog frame;
+  /*
+   * the absolute min-max range of a feature score is scaled to 
+   * 1000 positions on the colour threshold slider
+   */
+  private static final int SCALE_FACTOR_1K = 1000;
 
-  Frame owner;
+  private JVDialog frame;
 
-  FeatureRenderer fr;
+  private Frame owner;
 
-  FeatureSettings fs = null;
+  private FeatureRenderer fr;
 
-  // AlignmentPanel ap;
+  private FeatureSettings fs = null;
 
-  FeatureColourI cs;
+  private FeatureColourI cs;
 
-  FeatureColourI oldcs;
+  private FeatureColourI oldcs;
 
-  Hashtable oldgroupColours;
-
-  boolean adjusting = false;
+  private boolean adjusting = false;
 
   private float min, max;
 
-  String type = null;
+  private String type = null;
 
   private AlignFrame af = null;
 
-  public FeatureColourChooser(AlignFrame af, String type)
+  private Panel minColour = new Panel();
+
+  private Panel maxColour = new Panel();
+
+  private Choice threshold = new Choice();
+
+  private Scrollbar slider = new Scrollbar(Scrollbar.HORIZONTAL);
+
+  private TextField thresholdValue = new TextField(20);
+
+  private Checkbox thresholdIsMin = new Checkbox();
+
+  private Checkbox colourFromLabel = new Checkbox();
+
+  private GraphLine threshline;
+
+  /**
+   * Constructor given a context AlignFrame and a feature type. This is used
+   * when opening the graduated colour dialog from the Amend Feature dialog.
+   * 
+   * @param alignFrame
+   * @param featureType
+   */
+  public FeatureColourChooser(AlignFrame alignFrame, String featureType)
   {
-    this.af = af;
-    init(af.getSeqcanvas().getFeatureRenderer(), type);
+    this.af = alignFrame;
+    init(alignFrame.getSeqcanvas().getFeatureRenderer(), featureType);
   }
 
-  public FeatureColourChooser(FeatureSettings fsettings, String type)
+  /**
+   * Constructor given a context FeatureSettings and a feature type. This is
+   * used when opening the graduated colour dialog from Feature Settings.
+   * 
+   * @param fsettings
+   * @param featureType
+   */
+  public FeatureColourChooser(FeatureSettings fsettings, String featureType)
   {
     this.fs = fsettings;
-    init(fsettings.fr, type);
-    // this.ap = fsettings.ap;
+    init(fsettings.fr, featureType);
   }
 
-  private void init(FeatureRenderer frenderer, String type)
+  private void init(FeatureRenderer frenderer, String featureType)
   {
-    this.type = type;
+    this.type = featureType;
     fr = frenderer;
     float mm[] = fr.getMinMax().get(type)[0];
     min = mm[0];
     max = mm[1];
+    threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
     oldcs = fr.getFeatureColours().get(type);
     if (oldcs.isGraduatedColour())
     {
+      threshline.value = oldcs.getThreshold();
       cs = new FeatureColour((FeatureColour) oldcs, min, max);
     }
     else
@@ -128,7 +160,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
             : 0));
 
     adjusting = false;
-    changeColour();
+    changeColour(true);
     colourFromLabel.addItemListener(this);
     slider.addAdjustmentListener(this);
     slider.addMouseListener(this);
@@ -141,13 +173,12 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     frame.setVisible(true);
     if (frame.accept)
     {
-      changeColour();
+      changeColour(true);
     }
     else
     {
       // cancel
       reset();
-      PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
       frame.setVisible(false);
     }
   }
@@ -182,9 +213,13 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     thresholdIsMin.addItemListener(this);
 
     this.setLayout(new GridLayout(4, 1));
+    Panel jPanel1 = new Panel();
     jPanel1.setLayout(new FlowLayout());
+    Panel jPanel2 = new Panel();
     jPanel2.setLayout(new FlowLayout());
+    Panel jPanel3 = new Panel();
     jPanel3.setLayout(new GridLayout(1, 1));
+    Panel jPanel4 = new Panel();
     jPanel4.setLayout(new FlowLayout());
     jPanel1.setBackground(Color.white);
     jPanel2.setBackground(Color.white);
@@ -232,32 +267,6 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     this.add(jPanel4);// , java.awt.BorderLayout.CENTER);
   }
 
-  Panel minColour = new Panel();
-
-  Panel maxColour = new Panel();
-
-  Panel jPanel1 = new Panel();
-
-  Panel jPanel2 = new Panel();
-
-  Choice threshold = new Choice();
-
-  Panel jPanel3 = new Panel();
-
-  Panel jPanel4 = new Panel();
-
-  Scrollbar slider = new Scrollbar(Scrollbar.HORIZONTAL);
-
-  TextField thresholdValue = new TextField(20);
-
-  // BorderLayout borderLayout1 = new BorderLayout();
-
-  Checkbox thresholdIsMin = new Checkbox();
-
-  Checkbox colourFromLabel = new Checkbox();
-
-  private GraphLine threshline;
-
   @Override
   public void actionPerformed(ActionEvent evt)
   {
@@ -266,8 +275,13 @@ public class FeatureColourChooser extends Panel implements ActionListener,
       try
       {
         float f = new Float(thresholdValue.getText()).floatValue();
-        slider.setValue((int) (f * 1000));
+        slider.setValue((int) (f * SCALE_FACTOR_1K));
         adjustmentValueChanged(null);
+
+        /*
+         * force repaint of any Overview window or structure
+         */
+        changeColour(true);
       } catch (NumberFormatException ex)
       {
       }
@@ -282,7 +296,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     }
     else
     {
-      changeColour();
+      changeColour(true);
     }
   }
 
@@ -291,9 +305,13 @@ public class FeatureColourChooser extends Panel implements ActionListener,
   {
     maxColour.setEnabled(!colourFromLabel.getState());
     minColour.setEnabled(!colourFromLabel.getState());
-    changeColour();
+    changeColour(true);
   }
 
+  /**
+   * Handler called when the value of the threshold slider changes, either by
+   * user action or programmatically
+   */
   @Override
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
@@ -304,29 +322,32 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     }
   }
 
+  /**
+   * Responds to a change of colour threshold by computing the absolute value
+   * and refreshing the alignment.
+   */
   protected void valueChanged()
   {
     threshline.value = slider.getValue() / 1000f;
     cs.setThreshold(threshline.value);
-    changeColour();
+    changeColour(false);
     PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
-    // ap.paintAlignment(false);
   }
 
   public void minColour_actionPerformed(Color newCol)
   {
     if (newCol == null)
     {
-      UserDefinedColours udc = new UserDefinedColours(this,
+      new UserDefinedColours(this,
               minColour.getBackground(), owner,
-              MessageManager.getString("label.select_colour_minimum_value")); // frame.owner,
+              MessageManager.getString("label.select_colour_minimum_value"));
     }
     else
     {
       minColour.setBackground(newCol);
       minColour.setForeground(newCol);
       minColour.repaint();
-      changeColour();
+      changeColour(true);
     }
 
   }
@@ -335,10 +356,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
   {
     if (newCol == null)
     {
-
-      // UserDefinedColours udc = new UserDefinedColours(this,
-      // "Select Colour for Maximum Value",maxColour.getBackground(),true);
-      UserDefinedColours udc = new UserDefinedColours(this,
+      new UserDefinedColours(this,
               maxColour.getBackground(), owner,
               MessageManager.getString("label.select_colour_maximum_value"));
     }
@@ -347,11 +365,11 @@ public class FeatureColourChooser extends Panel implements ActionListener,
       maxColour.setBackground(newCol);
       maxColour.setForeground(newCol);
       maxColour.repaint();
-      changeColour();
+      changeColour(true);
     }
   }
 
-  void changeColour()
+  void changeColour(boolean updateOverview)
   {
     // Check if combobox is still adjusting
     if (adjusting)
@@ -359,14 +377,14 @@ public class FeatureColourChooser extends Panel implements ActionListener,
       return;
     }
 
-    int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD;
+    int thresholdOption = AnnotationColourGradient.NO_THRESHOLD;
     if (threshold.getSelectedIndex() == 1)
     {
-      aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
+      thresholdOption = AnnotationColourGradient.ABOVE_THRESHOLD;
     }
     else if (threshold.getSelectedIndex() == 2)
     {
-      aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
+      thresholdOption = AnnotationColourGradient.BELOW_THRESHOLD;
     }
 
     slider.setEnabled(true);
@@ -377,42 +395,34 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     acg.setColourByLabel(colourFromLabel.getState());
     maxColour.setEnabled(!colourFromLabel.getState());
     minColour.setEnabled(!colourFromLabel.getState());
-    if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
+    if (thresholdOption == AnnotationColourGradient.NO_THRESHOLD)
     {
       slider.setEnabled(false);
       thresholdValue.setEnabled(false);
       thresholdValue.setText("");
     }
 
-    else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
-            && threshline == null)
-    {
-      // todo visual indication of feature threshold
-      threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
-              "Threshold", Color.black);
-    }
-
-    if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
+    if (thresholdOption != AnnotationColourGradient.NO_THRESHOLD)
     {
       adjusting = true;
       acg.setThreshold(threshline.value);
 
-      float range = max * 1000f - min * 1000f;
-
-      slider.setMinimum((int) (min * 1000));
-      slider.setMaximum((int) (max * 1000));
-      slider.setValue((int) (threshline.value * 1000));
+      slider.setMinimum((int) (min * SCALE_FACTOR_1K));
+      slider.setMaximum((int) (max * SCALE_FACTOR_1K));
+      slider.setValue((int) (threshline.value * SCALE_FACTOR_1K));
       thresholdValue.setText(threshline.value + "");
       slider.setEnabled(true);
       thresholdValue.setEnabled(true);
       adjusting = false;
     }
 
-    acg.setAboveThreshold(true);
+    acg.setAboveThreshold(thresholdOption == AnnotationColourGradient.ABOVE_THRESHOLD);
+    acg.setBelowThreshold(thresholdOption == AnnotationColourGradient.BELOW_THRESHOLD);
+
     if (thresholdIsMin.getState()
-            && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
+            && thresholdOption != AnnotationColourGradient.NO_THRESHOLD)
     {
-      if (aboveThreshold == AnnotationColourGradient.ABOVE_THRESHOLD)
+      if (thresholdOption == AnnotationColourGradient.ABOVE_THRESHOLD)
       {
         acg = new FeatureColour(acg, threshline.value, max);
       }
@@ -424,16 +434,13 @@ public class FeatureColourChooser extends Panel implements ActionListener,
 
     fr.setColour(type, acg);
     cs = acg;
-    PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
-    // ap.paintAlignment(false);
+    fs.selectionChanged(updateOverview);
   }
 
   void reset()
   {
     fr.setColour(type, oldcs);
-    PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
-    // ap.paintAlignment(true);
-
+    fs.selectionChanged(true);
   }
 
   @Override
@@ -449,16 +456,19 @@ public class FeatureColourChooser extends Panel implements ActionListener,
   @Override
   public void mouseReleased(MouseEvent evt)
   {
-    if (evt.getSource() == minColour || evt.getSource() == maxColour)
+    if (evt.getSource() == minColour)
     {
-      // relay the event
-      actionPerformed(new ActionEvent(evt.getSource(), 1, "Clicked"));
+      minColour_actionPerformed(null);
+    }
+    else if (evt.getSource() == maxColour)
+    {
+      maxColour_actionPerformed(null);
     }
     else
     {
-      PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
+      changeColour(true);
+      // PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
     }
-    // ap.paintAlignment(true);
   }
 
   @Override
index 9d2f601..7d00afd 100755 (executable)
@@ -544,7 +544,7 @@ public class FeatureSettings extends Panel implements ItemListener,
       Checkbox check = (Checkbox) featurePanel.getComponent(i);
       check.setState(!check.getState());
     }
-    selectionChanged();
+    selectionChanged(true);
   }
 
   private ItemListener groupItemListener = new ItemListener()
@@ -567,10 +567,10 @@ public class FeatureSettings extends Panel implements ItemListener,
   @Override
   public void itemStateChanged(ItemEvent evt)
   {
-    selectionChanged();
+    selectionChanged(true);
   }
 
-  void selectionChanged()
+  void selectionChanged(boolean updateOverview)
   {
     Component[] comps = featurePanel.getComponents();
     int cSize = comps.length;
@@ -591,7 +591,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     fr.setFeaturePriority(data);
 
-    ap.paintAlignment(true);
+    ap.paintAlignment(updateOverview);
   }
 
   MyCheckbox selectedCheck;
index 7c6fad0..32507fe 100755 (executable)
@@ -27,6 +27,7 @@ import java.awt.Component;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 
 /**
@@ -37,7 +38,7 @@ import java.util.Vector;
  */
 public class PaintRefresher
 {
-  static Hashtable components;
+  static Map<String, Vector<Component>> components;
 
   /**
    * DOCUMENT ME!
@@ -51,12 +52,12 @@ public class PaintRefresher
   {
     if (components == null)
     {
-      components = new Hashtable();
+      components = new Hashtable<String, Vector<Component>>();
     }
 
     if (components.containsKey(seqSetId))
     {
-      Vector comps = (Vector) components.get(seqSetId);
+      Vector<Component> comps = components.get(seqSetId);
       if (!comps.contains(comp))
       {
         comps.addElement(comp);
@@ -64,7 +65,7 @@ public class PaintRefresher
     }
     else
     {
-      Vector vcoms = new Vector();
+      Vector<Component> vcoms = new Vector<>();
       vcoms.addElement(comp);
       components.put(seqSetId, vcoms);
     }
@@ -77,11 +78,9 @@ public class PaintRefresher
       return;
     }
 
-    Enumeration en = components.keys();
-    while (en.hasMoreElements())
+    for (String id : components.keySet())
     {
-      String id = en.nextElement().toString();
-      Vector comps = (Vector) components.get(id);
+      Vector<Component> comps = components.get(id);
       comps.removeElement(comp);
       if (comps.size() == 0)
       {
@@ -104,17 +103,17 @@ public class PaintRefresher
     }
 
     Component comp;
-    Vector comps = (Vector) components.get(id);
+    Vector<Component> comps = components.get(id);
 
     if (comps == null)
     {
       return;
     }
 
-    Enumeration e = comps.elements();
+    Enumeration<Component> e = comps.elements();
     while (e.hasMoreElements())
     {
-      comp = (Component) e.nextElement();
+      comp = e.nextElement();
 
       if (comp == source)
       {
@@ -240,8 +239,8 @@ public class PaintRefresher
 
   public static AlignmentPanel[] getAssociatedPanels(String id)
   {
-    Vector comps = (Vector) components.get(id);
-    Vector tmp = new Vector();
+    Vector<Component> comps = components.get(id);
+    Vector<Component> tmp = new Vector<>();
     int i, iSize = comps.size();
     for (i = 0; i < iSize; i++)
     {
index e4e3640..d000c73 100644 (file)
@@ -643,8 +643,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       wrappedBlock += startRes / cwidth;
       int startOffset = startRes % cwidth; // in case start is scrolled right
                                            // from 0
-      res = wrappedBlock * cwidth
-              + Math.min(cwidth - 1, startOffset + x / av.getCharWidth());
+      res = wrappedBlock * cwidth + startOffset
+              + +Math.min(cwidth - 1, x / av.getCharWidth());
     }
     else
     {
index 5594e1a..4172819 100644 (file)
@@ -49,29 +49,15 @@ import javax.swing.event.ChangeListener;
 public class FeatureColourChooser extends JalviewDialog
 {
   // FeatureSettings fs;
-  FeatureRenderer fr;
+  private FeatureRenderer fr;
 
   private FeatureColourI cs;
 
   private FeatureColourI oldcs;
 
-  /**
-   * 
-   * @return the last colour setting selected by user - either oldcs (which may
-   *         be a java.awt.Color) or the new GraduatedColor
-   */
-  public FeatureColourI getLastColour()
-  {
-    if (cs == null)
-    {
-      return oldcs;
-    }
-    return cs;
-  }
+  private AlignmentPanel ap;
 
-  AlignmentPanel ap;
-
-  boolean adjusting = false;
+  private boolean adjusting = false;
 
   final private float min;
 
@@ -79,25 +65,61 @@ public class FeatureColourChooser extends JalviewDialog
 
   final private float scaleFactor;
 
-  String type = null;
+  private String type = null;
+
+  private JPanel minColour = new JPanel();
+
+  private JPanel maxColour = new JPanel();
 
-  public FeatureColourChooser(FeatureRenderer frender, String type)
+  private JComboBox<String> threshold = new JComboBox<>();
+
+  private JSlider slider = new JSlider();
+
+  private JTextField thresholdValue = new JTextField(20);
+
+  // TODO implement GUI for tolower flag
+  // JCheckBox toLower = new JCheckBox();
+
+  private JCheckBox thresholdIsMin = new JCheckBox();
+
+  private JCheckBox colourByLabel = new JCheckBox();
+
+  private GraphLine threshline;
+
+  private Color oldmaxColour;
+
+  private Color oldminColour;
+
+  private ActionListener colourEditor = null;
+
+  /**
+   * Constructor
+   * 
+   * @param frender
+   * @param theType
+   */
+  public FeatureColourChooser(FeatureRenderer frender, String theType)
   {
-    this(frender, false, type);
+    this(frender, false, theType);
   }
 
-  public FeatureColourChooser(FeatureRenderer frender, boolean block,
-          String type)
+  /**
+   * Constructor, with option to make a blocking dialog (has to complete in the
+   * AWT event queue thread). Currently this option is always set to false.
+   * 
+   * @param frender
+   * @param blocking
+   * @param theType
+   */
+  FeatureColourChooser(FeatureRenderer frender, boolean blocking,
+          String theType)
   {
     this.fr = frender;
-    this.type = type;
+    this.type = theType;
     ap = fr.ap;
     String title = MessageManager.formatMessage(
-            "label.graduated_color_for_params", new String[] { type });
-    initDialogFrame(this, true, block, title, 480, 185);
-    // frame.setLayer(JLayeredPane.PALETTE_LAYER);
-    // Desktop.addInternalFrame(frame, "Graduated Feature Colour for "+type,
-    // 480, 145);
+            "label.graduated_color_for_params", new String[] { theType });
+    initDialogFrame(this, true, blocking, title, 480, 185);
 
     slider.addChangeListener(new ChangeListener()
     {
@@ -107,7 +129,7 @@ public class FeatureColourChooser extends JalviewDialog
         if (!adjusting)
         {
           thresholdValue.setText((slider.getValue() / scaleFactor) + "");
-          valueChanged();
+          sliderValueChanged();
         }
       }
     });
@@ -116,15 +138,18 @@ public class FeatureColourChooser extends JalviewDialog
       @Override
       public void mouseReleased(MouseEvent evt)
       {
+        /*
+         * only update Overview and/or structure colouring
+         * when threshold slider drag ends (mouse up)
+         */
         if (ap != null)
         {
           ap.paintAlignment(true);
         }
-        ;
       }
     });
 
-    float mm[] = fr.getMinMax().get(type)[0];
+    float mm[] = fr.getMinMax().get(theType)[0];
     min = mm[0];
     max = mm[1];
 
@@ -135,7 +160,7 @@ public class FeatureColourChooser extends JalviewDialog
      */
     scaleFactor = (max == min) ? 1f : 100f / (max - min);
 
-    oldcs = fr.getFeatureColours().get(type);
+    oldcs = fr.getFeatureColours().get(theType);
     if (!oldcs.isSimpleColour())
     {
       if (oldcs.isAutoScaled())
@@ -178,14 +203,15 @@ public class FeatureColourChooser extends JalviewDialog
       // initialise threshold slider and selector
       threshold.setSelectedIndex(cs.isAboveThreshold() ? 1 : 2);
       slider.setEnabled(true);
+      slider.setValue((int) (cs.getThreshold() * scaleFactor));
       thresholdValue.setEnabled(true);
       threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
-
+      threshline.value = cs.getThreshold();
     }
 
     adjusting = false;
 
-    changeColour();
+    changeColour(false);
     waitForInput();
   }
 
@@ -223,20 +249,22 @@ public class FeatureColourChooser extends JalviewDialog
       }
     });
     maxColour.setBorder(new LineBorder(Color.black));
-    minText.setText(MessageManager.getString("label.min"));
+    JLabel minText = new JLabel(MessageManager.getString("label.min"));
     minText.setFont(JvSwingUtils.getLabelFont());
-    maxText.setText(MessageManager.getString("label.max"));
+    JLabel maxText = new JLabel(MessageManager.getString("label.max"));
     maxText.setFont(JvSwingUtils.getLabelFont());
-    this.setLayout(borderLayout1);
-    jPanel2.setLayout(flowLayout1);
+    this.setLayout(new BorderLayout());
+    JPanel jPanel1 = new JPanel();
     jPanel1.setBackground(Color.white);
+    JPanel jPanel2 = new JPanel();
+    jPanel2.setLayout(new FlowLayout());
     jPanel2.setBackground(Color.white);
     threshold.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        threshold_actionPerformed(e);
+        threshold_actionPerformed();
       }
     });
     threshold.setToolTipText(MessageManager
@@ -247,13 +275,15 @@ public class FeatureColourChooser extends JalviewDialog
             .getString("label.threshold_feature_above_threshold")); // index 1
     threshold.addItem(MessageManager
             .getString("label.threshold_feature_below_threshold")); // index 2
-    jPanel3.setLayout(flowLayout2);
+
+    JPanel jPanel3 = new JPanel();
+    jPanel3.setLayout(new FlowLayout());
     thresholdValue.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        thresholdValue_actionPerformed(e);
+        thresholdValue_actionPerformed();
       }
     });
     slider.setPaintLabels(false);
@@ -277,7 +307,7 @@ public class FeatureColourChooser extends JalviewDialog
       @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
-        thresholdIsMin_actionPerformed(actionEvent);
+        thresholdIsMin_actionPerformed();
       }
     });
     colourByLabel.setBackground(Color.white);
@@ -291,69 +321,34 @@ public class FeatureColourChooser extends JalviewDialog
       @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
-        colourByLabel_actionPerformed(actionEvent);
+        colourByLabel_actionPerformed();
       }
     });
+
+    JPanel colourPanel = new JPanel();
     colourPanel.setBackground(Color.white);
     jPanel1.add(ok);
     jPanel1.add(cancel);
-    jPanel2.add(colourByLabel, java.awt.BorderLayout.WEST);
-    jPanel2.add(colourPanel, java.awt.BorderLayout.EAST);
+    jPanel2.add(colourByLabel, BorderLayout.WEST);
+    jPanel2.add(colourPanel, BorderLayout.EAST);
     colourPanel.add(minText);
     colourPanel.add(minColour);
     colourPanel.add(maxText);
     colourPanel.add(maxColour);
-    this.add(jPanel3, java.awt.BorderLayout.CENTER);
+    this.add(jPanel3, BorderLayout.CENTER);
     jPanel3.add(threshold);
     jPanel3.add(slider);
     jPanel3.add(thresholdValue);
     jPanel3.add(thresholdIsMin);
-    this.add(jPanel1, java.awt.BorderLayout.SOUTH);
-    this.add(jPanel2, java.awt.BorderLayout.NORTH);
+    this.add(jPanel1, BorderLayout.SOUTH);
+    this.add(jPanel2, BorderLayout.NORTH);
   }
 
-  JLabel minText = new JLabel();
-
-  JLabel maxText = new JLabel();
-
-  JPanel minColour = new JPanel();
-
-  JPanel maxColour = new JPanel();
-
-  JPanel colourPanel = new JPanel();
-
-  JPanel jPanel1 = new JPanel();
-
-  JPanel jPanel2 = new JPanel();
-
-  BorderLayout borderLayout1 = new BorderLayout();
-
-  JComboBox threshold = new JComboBox();
-
-  FlowLayout flowLayout1 = new FlowLayout();
-
-  JPanel jPanel3 = new JPanel();
-
-  FlowLayout flowLayout2 = new FlowLayout();
-
-  JSlider slider = new JSlider();
-
-  JTextField thresholdValue = new JTextField(20);
-
-  // TODO implement GUI for tolower flag
-  // JCheckBox toLower = new JCheckBox();
-
-  JCheckBox thresholdIsMin = new JCheckBox();
-
-  JCheckBox colourByLabel = new JCheckBox();
-
-  private GraphLine threshline;
-
-  private Color oldmaxColour;
-
-  private Color oldminColour;
-
-  public void minColour_actionPerformed()
+  /**
+   * Action on clicking the 'minimum colour' - open a colour chooser dialog, and
+   * set the selected colour (if the user does not cancel out of the dialog)
+   */
+  protected void minColour_actionPerformed()
   {
     Color col = JColorChooser.showDialog(this,
             MessageManager.getString("label.select_colour_minimum_value"),
@@ -364,10 +359,14 @@ public class FeatureColourChooser extends JalviewDialog
       minColour.setForeground(col);
     }
     minColour.repaint();
-    changeColour();
+    changeColour(true);
   }
 
-  public void maxColour_actionPerformed()
+  /**
+   * Action on clicking the 'maximum colour' - open a colour chooser dialog, and
+   * set the selected colour (if the user does not cancel out of the dialog)
+   */
+  protected void maxColour_actionPerformed()
   {
     Color col = JColorChooser.showDialog(this,
             MessageManager.getString("label.select_colour_maximum_value"),
@@ -378,10 +377,17 @@ public class FeatureColourChooser extends JalviewDialog
       maxColour.setForeground(col);
     }
     maxColour.repaint();
-    changeColour();
+    changeColour(true);
   }
 
-  void changeColour()
+  /**
+   * Constructs and sets the selected colour options as the colour for the
+   * feature type, and repaints the alignment, and optionally the Overview
+   * and/or structure viewer if open
+   * 
+   * @param updateOverview
+   */
+  void changeColour(boolean updateOverview)
   {
     // Check if combobox is still adjusting
     if (adjusting)
@@ -413,7 +419,6 @@ public class FeatureColourChooser extends JalviewDialog
     {
       acg = new FeatureColour(oldminColour = minColour.getBackground(),
               oldmaxColour = maxColour.getBackground(), min, max);
-
     }
 
     if (!hasThreshold)
@@ -425,7 +430,9 @@ public class FeatureColourChooser extends JalviewDialog
     }
     else if (threshline == null)
     {
-      // todo visual indication of feature threshold
+      /*
+       * todo not yet implemented: visual indication of feature threshold
+       */
       threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
     }
 
@@ -438,7 +445,8 @@ public class FeatureColourChooser extends JalviewDialog
 
       slider.setMinimum((int) (min * scaleFactor));
       slider.setMaximum((int) (max * scaleFactor));
-      slider.setValue((int) (threshline.value * scaleFactor));
+      // slider.setValue((int) (threshline.value * scaleFactor));
+      slider.setValue(Math.round(threshline.value * scaleFactor));
       thresholdValue.setText(threshline.value + "");
       slider.setMajorTickSpacing((int) (range / 10f));
       slider.setEnabled(true);
@@ -487,7 +495,7 @@ public class FeatureColourChooser extends JalviewDialog
     }
     fr.setColour(type, acg);
     cs = acg;
-    ap.paintAlignment(false);
+    ap.paintAlignment(updateOverview);
   }
 
   @Override
@@ -502,7 +510,7 @@ public class FeatureColourChooser extends JalviewDialog
   @Override
   public void okPressed()
   {
-    changeColour();
+    changeColour(false);
   }
 
   @Override
@@ -511,61 +519,80 @@ public class FeatureColourChooser extends JalviewDialog
     reset();
   }
 
+  /**
+   * Action when the user cancels the dialog. All previous settings should be
+   * restored and rendered on the alignment, and any linked Overview window or
+   * structure.
+   */
   void reset()
   {
     fr.setColour(type, oldcs);
-    ap.paintAlignment(false);
+    ap.paintAlignment(true);
     cs = null;
   }
 
-  public void thresholdCheck_actionPerformed(ActionEvent e)
-  {
-    changeColour();
-  }
-
-  public void annotations_actionPerformed(ActionEvent e)
-  {
-    changeColour();
-  }
-
-  public void threshold_actionPerformed(ActionEvent e)
+  /**
+   * Action on change of choice of No / Above / Below Threshold
+   */
+  protected void threshold_actionPerformed()
   {
-    changeColour();
+    changeColour(true);
   }
 
-  public void thresholdValue_actionPerformed(ActionEvent e)
+  /**
+   * Action on text entry of a threshold value
+   */
+  protected void thresholdValue_actionPerformed()
   {
     try
     {
       float f = Float.parseFloat(thresholdValue.getText());
       slider.setValue((int) (f * scaleFactor));
       threshline.value = f;
+
+      /*
+       * force repaint of any Overview window or structure
+       */
+      ap.paintAlignment(true);
     } catch (NumberFormatException ex)
     {
     }
   }
 
-  public void valueChanged()
+  /**
+   * Action on change of threshold slider value. This may be done interactively
+   * (by moving the slider), or programmatically (to update the slider after
+   * manual input of a threshold value).
+   */
+  protected void sliderValueChanged()
   {
-    threshline.value = slider.getValue() / scaleFactor;
+    /*
+     * squash rounding errors by forcing min/max of slider to 
+     * actual min/max of feature score range
+     */
+    int value = slider.getValue();
+    threshline.value = value == slider.getMaximum() ? max
+            : (value == slider.getMinimum() ? min : value / scaleFactor);
     cs.setThreshold(threshline.value);
-    changeColour();
-    ap.paintAlignment(false);
+
+    /*
+     * repaint alignment, but not Overview or structure,
+     * to avoid overload while dragging the slider
+     */
+    changeColour(false);
   }
 
-  public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
+  protected void thresholdIsMin_actionPerformed()
   {
-    changeColour();
+    changeColour(true);
   }
 
-  public void colourByLabel_actionPerformed(ActionEvent actionEvent)
+  protected void colourByLabel_actionPerformed()
   {
-    changeColour();
+    changeColour(true);
   }
 
-  ActionListener colourEditor = null;
-
-  public void addActionListener(ActionListener graduatedColorEditor)
+  void addActionListener(ActionListener graduatedColorEditor)
   {
     if (colourEditor != null)
     {
@@ -575,4 +602,19 @@ public class FeatureColourChooser extends JalviewDialog
     colourEditor = graduatedColorEditor;
   }
 
+  /**
+   * Answers the last colour setting selected by user - either oldcs (which may
+   * be a java.awt.Color) or the new GraduatedColor
+   * 
+   * @return
+   */
+  FeatureColourI getLastColour()
+  {
+    if (cs == null)
+    {
+      return oldcs;
+    }
+    return cs;
+  }
+
 }
index 065f97e..2d24512 100755 (executable)
@@ -154,7 +154,7 @@ public class IdPanel extends JPanel implements MouseListener,
       {
         av.getRanges().scrollRight(true);
       }
-      else
+      else if (!av.getWrapAlignment())
       {
         av.getRanges().scrollUp(false);
       }
@@ -165,7 +165,7 @@ public class IdPanel extends JPanel implements MouseListener,
       {
         av.getRanges().scrollRight(false);
       }
-      else
+      else if (!av.getWrapAlignment())
       {
         av.getRanges().scrollUp(true);
       }
index 6fbed49..26096e6 100644 (file)
@@ -216,8 +216,8 @@ public class SeqPanel extends JPanel implements MouseListener,
       wrappedBlock += startRes / cwidth;
       // allow for wrapped view scrolled right (possible from Overview)
       int startOffset = startRes % cwidth;
-      res = wrappedBlock * cwidth
-              + Math.min(cwidth - 1, startOffset + x / av.getCharWidth());
+      res = wrappedBlock * cwidth + startOffset
+              + +Math.min(cwidth - 1, x / av.getCharWidth());
     }
     else
     {
@@ -1616,7 +1616,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         av.getRanges().scrollRight(true);
 
       }
-      else
+      else if (!av.getWrapAlignment())
       {
         av.getRanges().scrollUp(false);
       }
@@ -1627,7 +1627,7 @@ public class SeqPanel extends JPanel implements MouseListener,
       {
         av.getRanges().scrollRight(false);
       }
-      else
+      else if (!av.getWrapAlignment())
       {
         av.getRanges().scrollUp(true);
       }
index 98f5bff..759101d 100644 (file)
@@ -335,6 +335,12 @@ public class FeatureRenderer extends FeatureRendererModel
         }
 
         Color featureColour = getColour(sequenceFeature);
+        if (featureColour == null)
+        {
+          // score feature outwith threshold for colouring
+          continue;
+        }
+
         boolean isContactFeature = sequenceFeature.isContactFeature();
 
         if (isContactFeature)
@@ -352,7 +358,7 @@ public class FeatureRenderer extends FeatureRendererModel
             drawnColour = featureColour;
           }
         }
-        else if (showFeature(sequenceFeature))
+        else
         {
           if (av.isShowSequenceFeaturesHeight()
                   && !Float.isNaN(sequenceFeature.score))
index f6addb8..40f38b6 100644 (file)
@@ -575,9 +575,17 @@ public abstract class FeatureRendererModel implements
   public Color getColour(SequenceFeature feature)
   {
     FeatureColourI fc = getFeatureStyle(feature.getType());
-    return fc.getColor(feature);
+    return fc.isColored(feature) ? fc.getColor(feature) : null;
   }
 
+  /**
+   * Answers true unless the feature has a score value which lies outside a
+   * minimum or maximum threshold configured for colouring. This method does not
+   * check feature type or group visibility.
+   * 
+   * @param sequenceFeature
+   * @return
+   */
   protected boolean showFeature(SequenceFeature sequenceFeature)
   {
     FeatureColourI fc = getFeatureStyle(sequenceFeature.type);
index d6f1e8b..cc7dca0 100644 (file)
@@ -75,9 +75,13 @@ public class FeaturesFileTest
      * updated - JAL-1904), and verify (some) feature group colours
      */
     colours = af.getFeatureRenderer().getFeatureColours();
-    assertEquals("26 feature group colours not found", 26, colours.size());
+    assertEquals("27 feature group colours not found", 27, colours.size());
     assertEquals(colours.get("Cath").getColour(), new Color(0x93b1d1));
     assertEquals(colours.get("ASX-MOTIF").getColour(), new Color(0x6addbb));
+    FeatureColourI kdColour = colours.get("kdHydrophobicity");
+    assertTrue(kdColour.isGraduatedColour());
+    assertTrue(kdColour.isAboveThreshold());
+    assertEquals(-2f, kdColour.getThreshold());
 
     /*
      * verify (some) features on sequences
index 9b68b43..4fc079e 100644 (file)
@@ -450,4 +450,69 @@ public class FeatureColourFinderTest
     FeatureColourFinder finder2 = new FeatureColourFinder(null);
     assertTrue(finder2.noFeaturesDisplayed());
   }
+
+  @Test(groups = "Functional")
+  public void testFindFeatureColour_graduatedWithThreshold()
+  {
+    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
+            2, 0f, "KdGroup"));
+    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4,
+            4, 5f, "KdGroup"));
+    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7,
+            7, 10f, "KdGroup"));
+  
+    /*
+     * graduated colour from 0 to 10
+     * above threshold value of 5
+     */
+    Color min = new Color(100, 50, 150);
+    Color max = new Color(200, 0, 100);
+    FeatureColourI fc = new FeatureColour(min, max, 0, 10);
+    fc.setAboveThreshold(true);
+    fc.setThreshold(5f);
+    fr.setColour("kd", fc);
+    fr.featuresAdded();
+    av.setShowSequenceFeatures(true);
+  
+    /*
+     * position 2, column 1, score 0 - below threshold - default colour
+     */
+    Color c = finder.findFeatureColour(Color.blue, seq, 1);
+    assertEquals(c, Color.blue);
+
+    /*
+     * position 4, column 3, score 5 - at threshold - default colour
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 3);
+    assertEquals(c, Color.blue);
+  
+    /*
+     * position 7, column 9, score 10 - maximum colour in range
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 9);
+    assertEquals(c, max);
+
+    /*
+     * now colour below threshold of 5
+     */
+    fc.setBelowThreshold(true);
+
+    /*
+     * position 2, column 1, score 0 - min colour
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 1);
+    assertEquals(c, min);
+
+    /*
+     * position 4, column 3, score 5 - at threshold - default colour
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 3);
+    assertEquals(c, Color.blue);
+
+    /*
+     * position 7, column 9, score 10 - above threshold - default colour
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 9);
+    assertEquals(c, Color.blue);
+  }
 }
index df8c162..842a0fd 100644 (file)
@@ -1109,4 +1109,53 @@ public class OverviewDimensionsShowHiddenTest
 
     hiddenRepSequences.put(allseqs[start], theseSeqs);
   }
+
+  /**
+   * Test setting of the box position, when there are hidden rows at the start
+   * of the alignment
+   */
+  @Test(groups = { "Functional" })
+  public void testFromMouseWithHiddenRowsAtStartWrapped()
+  {
+    vpranges.setWrappedMode(true);
+    od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
+    assertEquals(od.getBoxX(), 0);
+    assertEquals(od.getBoxY(), 0);
+    assertEquals(od.getBoxHeight(), boxHeight);
+    assertEquals(od.getBoxWidth(), boxWidth);
+    assertEquals(vpranges.getStartRes(), 0);
+    assertEquals(vpranges.getStartSeq(), 0);
+  
+    // hide rows at start and check updated box position is correct
+    // changes boxY but not boxheight
+    int lastHiddenRow = 30;
+    hideSequences(0, lastHiddenRow);
+  
+    od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+    assertEquals(od.getBoxX(), 0);
+    assertEquals(od.getBoxY(),
+            Math.round((float) (lastHiddenRow + 1)
+                    * od.getSequencesHeight() / alheight));
+    assertEquals(od.getBoxWidth(), boxWidth);
+    assertEquals(od.getBoxHeight(), boxHeight);
+  
+    // click in hidden rows - same result
+    mouseClick(od, 0, 0);
+    assertEquals(od.getBoxX(), 0);
+    int boxY = od.getBoxY();
+    assertEquals(
+            boxY,
+            Math.round((float) (lastHiddenRow + 1)
+                    * od.getSequencesHeight() / alheight));
+    assertEquals(od.getBoxWidth(), boxWidth);
+    assertEquals(od.getBoxHeight(), boxHeight);
+  
+    // click below hidden rows
+    // vertical move of overview box is suppressed in wrapped mode
+    mouseClick(od, 0, 150);
+    assertEquals(od.getBoxX(), 0);
+    assertEquals(od.getBoxY(), boxY); // unchanged
+    assertEquals(od.getBoxWidth(), boxWidth);
+    assertEquals(od.getBoxHeight(), boxHeight);
+  }
 }