JAL-2611 Added overview dimensions test for position in box
[jalview.git] / src / jalview / viewmodel / OverviewDimensions.java
index 17f56c9..f053a95 100644 (file)
  */
 package jalview.viewmodel;
 
-import jalview.api.AlignViewportI;
+import jalview.api.AlignmentColsCollectionI;
+import jalview.api.AlignmentRowsCollectionI;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenSequences;
 
-public class OverviewDimensions
-{
-  // Default width and height values
-  private static final int DEFAULT_GRAPH_HEIGHT = 20;
-
-  private static final int MAX_WIDTH = 400;
-
-  private static final int MIN_WIDTH = 120;
+import java.awt.Graphics;
 
-  private static final int MIN_SEQ_HEIGHT = 40;
+public abstract class OverviewDimensions
+{
+  protected static final int MAX_WIDTH = 400;
 
-  private static final int MAX_SEQ_HEIGHT = 300;
+  protected static final int MIN_WIDTH = 120;
 
-  private AlignViewportI av;
+  protected static final int MIN_SEQ_HEIGHT = 40;
 
-  private float scalew = 1f;
+  protected static final int MAX_SEQ_HEIGHT = 300;
 
-  private float scaleh = 1f;
+  private static final int DEFAULT_GRAPH_HEIGHT = 20;
 
-  // width of the overview panel
-  private int width;
+  protected int width;
 
-  // height of sequences part of the overview panel
-  private int sequencesHeight;
+  protected int sequencesHeight;
 
-  // height of the graphs part of the overview panel
-  private int graphHeight = DEFAULT_GRAPH_HEIGHT;
+  protected int graphHeight = DEFAULT_GRAPH_HEIGHT;
 
-  // dimensions of box outlining current extent of view in alignment panel
-  // location of left side of box
-  private int boxX = -1;
+  protected int boxX = -1;
 
-  // location of bottom of box
-  private int boxY = -1;
+  protected int boxY = -1;
 
-  // width of box
-  private int boxWidth = -1;
+  protected int boxWidth = -1;
 
-  // height of box
-  private int boxHeight = -1;
+  protected int boxHeight = -1;
 
-  private int scrollCol = -1;
+  protected int alwidth;
 
-  private int scrollRow = -1;
+  protected int alheight;
 
-  public OverviewDimensions(AlignViewportI avi)
+  /**
+   * Create an OverviewDimensions object
+   * 
+   * @param ranges
+   *          positional properties of the viewport
+   * @param showAnnotationPanel
+   *          true if the annotation panel is to be shown, false otherwise
+   */
+  public OverviewDimensions(ViewportRanges ranges,
+          boolean showAnnotationPanel)
   {
-    this.av = avi;
-
     // scale the initial size of overviewpanel to shape of alignment
-    float initialScale = (float) av.getAlignment().getWidth()
-            / (float) av.getAlignment().getHeight();
+    float initialScale = (float) ranges.getAbsoluteAlignmentWidth()
+            / (float) ranges.getAbsoluteAlignmentHeight();
 
-    // TODO: in applet this was getSequenceConsensusHash()
-    // check if it makes any functional difference
-    if (av.getAlignmentConservationAnnotation() == null)
+    if (!showAnnotationPanel)
     {
       graphHeight = 0;
     }
 
-    if (av.getAlignment().getWidth() > av.getAlignment().getHeight())
+    if (ranges.getAbsoluteAlignmentWidth() > ranges
+            .getAbsoluteAlignmentHeight())
     {
       // wider
       width = MAX_WIDTH;
-      sequencesHeight = (int) (MAX_WIDTH / initialScale);
+      sequencesHeight = Math.round(MAX_WIDTH / initialScale);
       if (sequencesHeight < MIN_SEQ_HEIGHT)
       {
         sequencesHeight = MIN_SEQ_HEIGHT;
@@ -95,7 +92,7 @@ public class OverviewDimensions
     else
     {
       // taller
-      width = (int) (MAX_WIDTH * initialScale);
+      width = Math.round(MAX_WIDTH * initialScale);
       sequencesHeight = MAX_SEQ_HEIGHT;
 
       if (width < MIN_WIDTH)
@@ -106,157 +103,67 @@ public class OverviewDimensions
   }
 
   /**
-   * Check box dimensions and scroll positions and correct if necessary
+   * Draw the overview panel's viewport box on a graphics object
+   * 
+   * @param g
+   *          the graphics object to draw on
    */
-  public void checkValid()
+  public void drawBox(Graphics g)
   {
-    if (boxY < 0)
-    {
-      boxY = 0;
-    }
-
-    if (boxY > (sequencesHeight - boxHeight))
-    {
-      boxY = sequencesHeight - boxHeight + 1;
-    }
-
-    if (boxX < 0)
-    {
-      boxX = 0;
-    }
-
-    if (boxX > (width - boxWidth))
-    {
-      if (av.hasHiddenColumns())
-      {
-        // Try smallest possible box
-        boxWidth = (int) ((av.getEndRes() - av.getStartRes() + 1)
-                * av.getCharWidth() * scalew);
-      }
-      boxX = width - boxWidth;
-    }
-
-    scrollCol = (int) (boxX / scalew / av.getCharWidth());
-    scrollRow = (int) (boxY / scaleh / av.getCharHeight());
-
-    if (av.hasHiddenColumns())
-    {
-      if (!av.getColumnSelection().isVisible(scrollCol))
-      {
-        return;
-      }
-
-      scrollCol = av.getColumnSelection().findColumnPosition(scrollCol);
-    }
-
-    if (av.hasHiddenRows())
-    {
-      scrollRow = av.getAlignment().getHiddenSequences()
-              .findIndexWithoutHiddenSeqs(scrollRow);
-    }
+    g.drawRect(boxX, boxY, boxWidth, boxHeight);
+    g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2);
   }
 
-  /**
-   * Update the overview panel box when the associated alignment panel is
-   * changed
-   * 
-   */
-  public void setBoxPosition()
+  public int getBoxX()
   {
-    updateScales();
-
-    int startRes = av.getStartRes();
-    int endRes = av.getEndRes();
-
-    if (av.hasHiddenColumns())
-    {
-      startRes = av.getColumnSelection().adjustForHiddenColumns(startRes);
-      endRes = av.getColumnSelection().adjustForHiddenColumns(endRes);
-    }
-
-    int startSeq = av.getStartSeq();
-    int endSeq = av.getEndSeq();
-
-    if (av.hasHiddenRows())
-    {
-      startSeq = av.getAlignment().getHiddenSequences()
-              .adjustForHiddenSeqs(startSeq);
-
-      endSeq = av.getAlignment().getHiddenSequences()
-              .adjustForHiddenSeqs(endSeq);
-
-    }
-
-    boxX = (int) (startRes * av.getCharWidth() * scalew);
-    boxY = (int) (startSeq * av.getCharHeight() * scaleh);
-
-    if (av.hasHiddenColumns())
-    {
-      boxWidth = (int) ((endRes - startRes + 1) * av.getCharWidth() * scalew);
-    }
-    else
-    {
-      boxWidth = (int) ((endRes - startRes + 1) * av.getCharWidth() * scalew);
-    }
-
-    boxHeight = (int) ((endSeq - startSeq) * av.getCharHeight() * scaleh);
+    return boxX;
   }
 
-  /**
-   * Update width and height scales in terms of the alignment width and height
-   */
-  public void updateScales()
+  public int getBoxY()
   {
-    int alwidth = av.getAlignment().getWidth();
-    int alheight = av.getAlignment().getHeight()
-            + av.getAlignment().getHiddenSequences().getSize();
-
-    int fullsizeWidth = alwidth * av.getCharWidth();
-    int fullsizeHeight = alheight * av.getCharHeight();
-
-    scalew = (float) width / fullsizeWidth;
-    scaleh = (float) sequencesHeight / fullsizeHeight;
+    return boxY;
   }
 
-  // don't like this, scroll vals are separate from setting code
-  public int getScrollCol()
+  public int getBoxWidth()
   {
-    return scrollCol;
+    return boxWidth;
   }
 
-  public int getScrollRow()
+  public int getBoxHeight()
   {
-    return scrollRow;
+    return boxHeight;
   }
 
-  public int getBoxX()
+  public int getWidth()
   {
-    return boxX;
+    return width;
   }
 
-  public int getBoxY()
+  public int getHeight()
   {
-    return boxY;
+    return sequencesHeight + graphHeight;
   }
 
-  public int getBoxWidth()
+  public int getSequencesHeight()
   {
-    return boxWidth;
+    return sequencesHeight;
   }
 
-  public int getBoxHeight()
+  public int getGraphHeight()
   {
-    return boxHeight;
+    return graphHeight;
   }
 
-  public void setBoxX(int x)
+  public float getPixelsPerCol()
   {
-    boxX = x;
+    resetAlignmentDims();
+    return (float) width / alwidth;
   }
 
-  public void setBoxY(int y)
+  public float getPixelsPerSeq()
   {
-    boxY = y;
+    resetAlignmentDims();
+    return (float) sequencesHeight / alheight;
   }
 
   public void setWidth(int w)
@@ -269,23 +176,83 @@ public class OverviewDimensions
     sequencesHeight = h - graphHeight;
   }
 
-  public int getWidth()
-  {
-    return width;
-  }
+  /**
+   * Update the viewport location from a mouse click in the overview panel
+   * 
+   * @param mousex
+   *          x location of mouse
+   * @param mousey
+   *          y location of mouse
+   * @param hiddenSeqs
+   *          the alignment's hidden sequences
+   * @param hiddenCols
+   *          the alignment's hidden columns
+   */
+  public abstract void updateViewportFromMouse(int mousex, int mousey,
+          HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
 
-  public int getHeight()
-  {
-    return sequencesHeight + graphHeight;
-  }
+  /**
+   * Set the overview panel's box position to match the viewport
+   * 
+   * @param hiddenSeqs
+   *          the alignment's hidden sequences
+   * @param hiddenCols
+   *          the alignment's hidden columns
+   */
+  public abstract void setBoxPosition(HiddenSequences hiddenSeqs,
+          HiddenColumns hiddenCols);
 
-  public int getSequencesHeight()
+  /**
+   * Get the collection of columns used by this overview dimensions object
+   * 
+   * @param hiddenCols
+   *          the alignment's hidden columns
+   * @return a column collection
+   */
+  public abstract AlignmentColsCollectionI getColumns(AlignmentI al);
+
+  /**
+   * Get the collection of rows used by this overview dimensions object
+   * 
+   * @param al
+   *          the alignment
+   * @return a row collection
+   */
+  public abstract AlignmentRowsCollectionI getRows(AlignmentI al);
+
+  /**
+   * Updates overview dimensions to account for current alignment dimensions
+   */
+  protected abstract void resetAlignmentDims();
+
+  protected void setBoxPosition(int startRes, int startSeq, int vpwidth,
+          int vpheight)
   {
-    return sequencesHeight;
+    resetAlignmentDims();
+
+    // boxX, boxY is the x,y location equivalent to startRes, startSeq
+    boxX = Math.round((float) startRes * width / alwidth);
+    boxY = Math.round((float) startSeq * sequencesHeight / alheight);
+
+    // boxWidth is the width in residues translated to pixels
+    boxWidth = Math.round((float) vpwidth * width / alwidth);
+
+    // boxHeight is the height in sequences translated to pixels
+    boxHeight = Math.round((float) vpheight * sequencesHeight / alheight);
   }
 
-  public int getGraphHeight()
+  /**
+   * Answers if a mouse position is in the overview's red box
+   * 
+   * @param x
+   *          mouse x position
+   * @param y
+   *          mouse y position
+   * @return true if (x,y) is inside the box
+   */
+  protected boolean isPositionInBox(int x, int y)
   {
-    return graphHeight;
+    return (x > boxX && y > boxY && boxX + x < boxWidth
+            && boxY + y < boxHeight);
   }
-}
+}
\ No newline at end of file