*/
package jalview.viewmodel;
-import jalview.api.AlignViewportI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenSequences;
import java.awt.Graphics;
private static final int MAX_SEQ_HEIGHT = 300;
- private AlignViewportI av;
-
- private ViewportPositionProps posProps;
-
- private float scalew = 1f;
-
- private float scaleh = 1f;
-
// width of the overview panel
private int width;
// height of box
private int boxHeight = -1;
+ // scroll position in viewport corresponding to boxX
private int scrollCol = -1;
+ // scroll position in viewport corresponding to boxY
private int scrollRow = -1;
- public OverviewDimensions(AlignViewportI avi)
+ /**
+ * Create an OverviewDimensions object
+ *
+ * @param props
+ * positional properties of the viewport
+ * @param showAnnotationPanel
+ * true if the annotation panel is to be shown, false otherwise
+ */
+ public OverviewDimensions(ViewportPositionProps props,
+ boolean showAnnotationPanel)
{
- this.av = avi;
- this.posProps = av.getPosProps();
-
// scale the initial size of overviewpanel to shape of alignment
- float initialScale = (float) av.getAlignment().getWidth()
- / (float) av.getAlignment().getHeight();
+ float initialScale = (float) props.getAbsoluteAlignmentWidth()
+ / (float) props.getAbsoluteAlignmentHeight();
- // TODO: in applet this was getSequenceConsensusHash()
- // check if it makes any functional difference
- if (av.getAlignmentConservationAnnotation() == null)
+ if (!showAnnotationPanel)
{
graphHeight = 0;
}
- if (posProps.getAlignmentWidthInCols() > posProps
- .getAlignmentHeightInRows())
+ if (props.getAbsoluteAlignmentWidth() > props
+ .getAbsoluteAlignmentHeight())
{
// wider
width = MAX_WIDTH;
/**
* Check box dimensions and scroll positions and correct if necessary
+ *
+ * @param mousex
+ * x position in overview panel
+ * @param mousey
+ * y position in overview panel
+ * @param hiddenSeqs
+ * hidden sequences
+ * @param hiddenCols
+ * hidden columns
+ * @param props
+ * viewport position properties
*/
- public void setBoxPositionByMouse(int x, int y)
+ public void updateViewportFromMouse(int mousex, int mousey,
+ HiddenSequences hiddenSeqs, ColumnSelection hiddenCols,
+ ViewportPositionProps props)
{
- boxX = x;
- boxY = y;
- if (boxY < 0)
- {
- boxY = 0;
- }
- else if (boxY > (sequencesHeight - boxHeight))
+ int x = mousex;
+ int y = mousey;
+
+ int alwidth = props.getAbsoluteAlignmentWidth();
+ int alheight = props.getAbsoluteAlignmentHeight();
+
+ if (x < 0)
{
- boxY = sequencesHeight - boxHeight + 1;
+ x = 0;
}
- if (boxX < 0)
+ if (y < 0)
{
- boxX = 0;
+ y = 0;
}
- else if (boxX > (width - boxWidth))
- {
- if (av.hasHiddenColumns())
- {
- // Try smallest possible box
- boxWidth = (int) (posProps.convertResiduesToPixels(posProps
- .getEndRes() - posProps.getStartRes() + 1) * scalew);
- // boxWidth = (int) ((av.getEndRes() - av.getStartRes() + 1)
- // * av.getCharWidth() * scalew);
- }
- boxX = width - boxWidth;
- }
+ //
+ // Convert x value to residue position
+ //
+
+ // need to determine where scrollCol should be, given x
+ // to do this also need to know width of viewport, and some hidden column
+ // correction
- scrollCol = posProps.convertPixelsToResidues(Math.round(boxX / scalew));
- scrollRow = posProps
- .convertPixelsToSequences(Math.round(boxY / scaleh));
+ // convert x to residues - this is an absolute position
+ int xAsRes = Math.round((float) x * alwidth / width);
- // scrollCol = (int) (boxX / scalew / av.getCharWidth());
- // scrollRow = (int) (boxY / scaleh / av.getCharHeight());
+ // get viewport width in residues
+ int vpwidth = props.getEndRes() - props.getStartRes() + 1;
- if (av.hasHiddenColumns())
+ // get where x should be when accounting for hidden cols
+ // if x is in a hidden col region, shift to left - but we still need
+ // absolute position
+ // so convert back after getting visible region position
+ int visXAsRes = hiddenCols.findColumnPosition(xAsRes);
+
+ // check in case we went off the edge of the alignment
+ int visAlignWidth = hiddenCols.findColumnPosition(alwidth - 1);
+ if (visXAsRes + vpwidth - 1 > visAlignWidth)
{
- if (!av.getColumnSelection().isVisible(scrollCol))
+ // went past the end of the alignment, adjust backwards
+
+ // if last position was before the end of the alignment, need to update
+ if ((scrollCol + vpwidth - 1) < visAlignWidth)
{
- return;
+ visXAsRes = hiddenCols.findColumnNToLeft(vpwidth - 1, alwidth - 1);
+ }
+ else
+ {
+ visXAsRes = scrollCol;
}
-
- scrollCol = av.getColumnSelection().findColumnPosition(scrollCol);
}
- if (av.hasHiddenRows())
- {
- scrollRow = av.getAlignment().getHiddenSequences()
- .findIndexWithoutHiddenSeqs(scrollRow);
- }
- }
+ //
+ // Convert y value to sequence position
+ //
- /**
- * Update the overview panel box when the associated alignment panel is
- * changed
- *
- */
- public void setBoxPosition()
- {
- updateScales();
+ // convert y to residues
+ int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
- int startRes = av.getStartRes();
- int endRes = av.getEndRes();
+ // get viewport height in sequences
+ // add 1 because height includes both endSeq and startSeq
+ int vpheight = props.getEndSeq() - props.getStartSeq() + 1;
- if (av.hasHiddenColumns())
- {
- startRes = av.getColumnSelection().adjustForHiddenColumns(startRes);
- endRes = av.getColumnSelection().adjustForHiddenColumns(endRes);
- }
+ // get where y should be when accounting for hidden rows
+ // if y is in a hidden row region, shift up - but we still need absolute
+ // position,
+ // so convert back after getting visible region position
+ yAsSeq = hiddenSeqs.adjustForHiddenSeqs(hiddenSeqs
+ .findIndexWithoutHiddenSeqs(yAsSeq));
- int startSeq = av.getStartSeq();
- int endSeq = av.getEndSeq();
+ // get where end seq should be by adding the viewport height on
+ int endSeq = yAsSeq + vpheight - 1;
- if (av.hasHiddenRows())
+ // check in case we went off the edge of the alignment
+ int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
+ int visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
+ if (hiddenSeqs.findIndexWithoutHiddenSeqs(endSeq) > visAlignHeight)
{
- startSeq = av.getAlignment().getHiddenSequences()
- .adjustForHiddenSeqs(startSeq);
-
- endSeq = av.getAlignment().getHiddenSequences()
- .adjustForHiddenSeqs(endSeq);
+ // went past the end of the alignment, adjust backwards
+ if ((scrollRow + vpheight - 1) < visAlignHeight)
+ {
+ visYAsRes = hiddenSeqs
+ .findIndexNAboveRow(vpheight - 1, alheight - 1);
+ }
+ else
+ {
+ visYAsRes = scrollRow;
+ }
}
- boxX = Math.round(posProps.convertResiduesToPixels(startRes) * scalew);
- boxY = Math.round(posProps.convertSequencesToPixels(startSeq) * scaleh);
-
- // boxX = (int) (startRes * av.getCharWidth() * scalew);
- // boxY = (int) (startSeq * av.getCharHeight() * scaleh);
-
- boxWidth = Math.round(posProps.convertResiduesToPixels(endRes
- - startRes
- + 1) * scalew);
- boxHeight = Math.round(posProps.convertSequencesToPixels(endSeq
- - startSeq)
- * scaleh);
+ // convert absolute positions back to visible alignment positions for
+ // viewport scrolling
+ scrollCol = visXAsRes;
+ scrollRow = visYAsRes; // hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
- // boxWidth = (int) ((endRes - startRes + 1) * av.getCharWidth() * scalew);
- // boxHeight = (int) ((endSeq - startSeq) * av.getCharHeight() * scaleh);
}
/**
- * Update width and height scales in terms of the alignment width and height
+ * Update the overview panel box when the associated alignment panel is
+ * changed
+ *
+ * @param hiddenSeqs
+ * hidden sequences
+ * @param hiddenCols
+ * hidden columns
+ * @param props
+ * viewport position properties
*/
- public void updateScales()
+ public void setBoxPosition(HiddenSequences hiddenSeqs,
+ ColumnSelection hiddenCols, ViewportPositionProps props)
{
- 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;
+ int alwidth = props.getAbsoluteAlignmentWidth();
+ int alheight = props.getAbsoluteAlignmentHeight();
+
+ // work with absolute values of startRes and endRes
+ int startRes = hiddenCols.adjustForHiddenColumns(props.getStartRes());
+ int endRes = hiddenCols.adjustForHiddenColumns(props.getEndRes());
+
+ // work with absolute values of startSeq and endSeq
+ int startSeq = hiddenSeqs.adjustForHiddenSeqs(props.getStartSeq());
+ int endSeq = hiddenSeqs.adjustForHiddenSeqs(props.getEndSeq());
+
+ // 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
+ // since the box includes both the start and end residues, add 1 to the
+ // difference
+ boxWidth = Math
+ .round((float) (endRes - startRes + 1) * width / alwidth);
+ // boxHeight is the height in sequences translated to pixels
+ boxHeight = Math.round((float) (endSeq - startSeq + 1)
+ * sequencesHeight
+ / alheight);
}
/**
return boxY;
}
+ // TODO should be removed, when unit test has mock Graphics object available
public int getBoxWidth()
{
return boxWidth;
}
+ // TODO should be removed, when unit test has mock Graphics object available
public int getBoxHeight()
{
return boxHeight;
}
- public void setBoxX(int x)
- {
- boxX = x;
- }
-
- public void setBoxY(int y)
- {
- boxY = y;
- }
-
public void setWidth(int w)
{
width = w;