import java.awt.BorderLayout;
import java.awt.CheckboxMenuItem;
+import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Panel;
import java.awt.PopupMenu;
private boolean updateRunning = false;
+ private boolean draggingBox = false;
+
public OverviewPanel(AlignmentPanel alPanel)
{
this.av = alPanel.av;
@Override
public void mouseMoved(MouseEvent evt)
{
+ if (od.isPositionInBox(evt.getX(), evt.getY()))
+ {
+ // display drag cursor at mouse position
+ setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+ }
+ else
+ {
+ // reset cursor
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
}
@Override
public void mousePressed(MouseEvent evt)
{
- mouseAction(evt);
+ if ((evt.getModifiers()
+ & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+ {
+ if (!Platform.isAMac())
+ {
+ showPopupMenu(evt);
+ }
+ }
+ else
+ {
+ if (!od.isPositionInBox(evt.getX(), evt.getY()))
+ {
+ // don't do anything if the mouse press is in the overview's box
+ // (wait to see if it's a drag instead)
+ // otherwise update the viewport
+ od.updateViewportFromMouse(evt.getX(), evt.getY(),
+ av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ }
+ else
+ {
+ draggingBox = true;
+ od.setDragPoint(evt.getX(), evt.getY(),
+ av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ }
+ }
}
@Override
public void mouseReleased(MouseEvent evt)
{
- mouseAction(evt);
+ if (draggingBox)
+ {
+ draggingBox = false;
+ }
}
@Override
public void mouseDragged(MouseEvent evt)
{
- mouseAction(evt);
- }
-
- private void mouseAction(MouseEvent evt)
- {
if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
{
if (!Platform.isAMac())
}
else
{
- od.updateViewportFromMouse(evt.getX(), evt.getY(), av.getAlignment()
- .getHiddenSequences(), av.getAlignment().getHiddenColumns());
+ if (draggingBox)
+ {
+ // set the mouse position as a fixed point in the box
+ // and drag relative to that position
+ od.adjustViewportFromMouse(evt.getX(), evt.getY(),
+ av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ }
+ else
+ {
+ od.updateViewportFromMouse(evt.getX(), evt.getY(),
+ av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ }
ap.paintAlignment(false);
}
}
*/
public void updateOverviewImage()
{
+ if (oviewCanvas == null)
+ {
+ /*
+ * panel has been disposed
+ */
+ return;
+ }
+
if ((getSize().width > 0) && (getSize().height > 0))
{
od.setWidth(getSize().width);
oviewCanvas.resetOviewDims(od);
updateOverviewImage();
}
+
+ /**
+ * Removes this object as a property change listener, and nulls references
+ */
+ protected void dispose()
+ {
+ try
+ {
+ av.getRanges().removePropertyChangeListener(this);
+ } finally
+ {
+ av = null;
+ oviewCanvas = null;
+ ap = null;
+ od = null;
+ }
+ }
}
int absAlignmentIndex = alignment.findIndex(sequence);
int alignmentIndex = adjustForHiddenSeqs(absAlignmentIndex);
- if (hiddenSequences[alignmentIndex] != null)
+ if (alignmentIndex < 0 || hiddenSequences[alignmentIndex] != null)
{
System.out.println("ERROR!!!!!!!!!!!");
+ return;
}
hiddenSequences[alignmentIndex] = sequence;
}
/**
- * Convert absolute alignment index to visible alignment index
+ * Convert absolute alignment index to visible alignment index (or -1 if
+ * before the first visible sequence)
*
* @param alignmentIndex
* @return
return startRow - visibleDistance;
}
- int index = startRow;
+ int index = Math.min(startRow, hiddenSequences.length - 1);
int count = 0;
while ((index > -1) && (count < visibleDistance))
{
import jalview.viewmodel.ViewportListenerI;
import java.awt.BorderLayout;
+import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
private boolean showHidden = true;
+ private boolean draggingBox = false;
+
/**
* Creates a new OverviewPanel object.
*
@Override
public void mouseDragged(MouseEvent evt)
{
- if (!SwingUtilities.isRightMouseButton(evt)
- && !av.getWrapAlignment())
+ if (!SwingUtilities.isRightMouseButton(evt))
{
- od.updateViewportFromMouse(evt.getX(), evt.getY(), av
+ if (draggingBox)
+ {
+ // set the mouse position as a fixed point in the box
+ // and drag relative to that position
+ od.adjustViewportFromMouse(evt.getX(),
+ evt.getY(), av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ }
+ else
+ {
+ od.updateViewportFromMouse(evt.getX(), evt.getY(), av
.getAlignment().getHiddenSequences(), av.getAlignment()
.getHiddenColumns());
+ }
-
+ }
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent evt)
+ {
+ if (od.isPositionInBox(evt.getX(), evt.getY()))
+ {
+ // display drag cursor at mouse position
+ setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+ }
+ else
+ {
+ // reset cursor
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
});
showPopupMenu(evt);
}
}
- else if (!av.getWrapAlignment())
+ else
+ // if (!av.getWrapAlignment())
{
- od.updateViewportFromMouse(evt.getX(), evt.getY(), av
- .getAlignment().getHiddenSequences(), av.getAlignment()
- .getHiddenColumns());
+ if (!od.isPositionInBox(evt.getX(), evt.getY()))
+ {
+ // don't do anything if the mouse press is in the overview's box
+ // (wait to see if it's a drag instead)
+ // otherwise update the viewport
+ od.updateViewportFromMouse(evt.getX(), evt.getY(),
+ av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ }
+ else
+ {
+ draggingBox = true;
+ od.setDragPoint(evt.getX(), evt.getY(),
+ av.getAlignment().getHiddenSequences(),
+ av.getAlignment().getHiddenColumns());
+ }
+ }
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent evt)
+ {
+ if (draggingBox)
+ {
+ draggingBox = false;
}
}
showPopupMenu(evt);
}
}
-
-
});
updateOverviewImage();
*/
public void updateOverviewImage()
{
+ if (oviewCanvas == null)
+ {
+ /*
+ * panel has been disposed
+ */
+ return;
+ }
+
if ((getWidth() > 0) && (getHeight() > 0))
{
od.setWidth(getWidth());
Thread thread = new Thread(this);
thread.start();
repaint();
-
}
@Override
{
setBoxPosition();
}
+
+ /**
+ * Removes this object as a property change listener, and nulls references
+ */
+ protected void dispose()
+ {
+ try
+ {
+ av.getRanges().removePropertyChangeListener(this);
+ } finally
+ {
+ av = null;
+ oviewCanvas = null;
+ ap = null;
+ od = null;
+ }
+ }
}
HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
/**
+ * Update the viewport location from a mouse drag within the overview's box
+ *
+ * @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 adjustViewportFromMouse(int mousex, int mousey,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
+
+ /**
+ * Initialise dragging from the mouse - must be called on initial mouse click
+ * before using adjustViewportFromMouse in drag operations
+ *
+ * @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 setDragPoint(int x, int y,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
+
+ /*
+ * Move the viewport so that the top left corner of the overview's box
+ * is at the mouse position (leftx, topy)
+ */
+ protected abstract void updateViewportFromTopLeft(int leftx, int topy,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
+
+ /**
* Set the overview panel's box position to match the viewport
*
* @param hiddenSeqs
*/
protected abstract void resetAlignmentDims();
+ /*
+ * Given the box coordinates in residues and sequences, set the box dimensions in the overview window
+ */
protected void setBoxPosition(int startRes, int startSeq, int vpwidth,
int vpheight)
{
resetAlignmentDims();
// boxX, boxY is the x,y location equivalent to startRes, startSeq
- boxX = Math.round((float) startRes * width / alwidth);
+ int xPos = Math.min(startRes, alwidth - vpwidth + 1);
+ boxX = Math.round((float) xPos * width / alwidth);
boxY = Math.round((float) startSeq * sequencesHeight / alheight);
// boxWidth is the width in residues translated to pixels
// boxHeight is the height in sequences translated to pixels
boxHeight = Math.round((float) vpheight * sequencesHeight / alheight);
}
+
+ /**
+ * 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
+ */
+ public boolean isPositionInBox(int x, int y)
+ {
+ return (x > boxX && y > boxY && x < boxX + boxWidth
+ && y < boxY + boxHeight);
+ }
+
+ /*
+ * Given the centre x position, calculate the box's left x position
+ */
+ protected abstract int getLeftXFromCentreX(int mousex, HiddenColumns hidden);
+
+ /*
+ * Given the centre y position, calculate the box's top y position
+ */
+ protected abstract int getTopYFromCentreY(int mousey,
+ HiddenSequences hidden);
+
}
{
private ViewportRanges ranges;
+ private int xdiff; // when dragging, difference in alignment units between
+ // start residue and original mouse click position
+
+ private int ydiff; // when dragging, difference in alignment units between
+ // start sequence and original mouse click position
+
public OverviewDimensionsHideHidden(ViewportRanges vpranges,
boolean showAnnotationPanel)
{
public void updateViewportFromMouse(int mousex, int mousey,
HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
{
- resetAlignmentDims();
+ int xAsRes = getLeftXFromCentreX(mousex, hiddenCols);
+ int yAsSeq = getTopYFromCentreY(mousey, hiddenSeqs);
+
+ updateViewportFromTopLeft(xAsRes, yAsSeq, hiddenSeqs, hiddenCols);
+
+ }
+
+ @Override
+ public void adjustViewportFromMouse(int mousex, int mousey,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
+ {
+ // calculate translation in pixel terms:
+ // get mouse location in viewport coords, add translation in viewport
+ // coords, and update viewport as usual
+ int vpx = Math.round((float) mousex * alwidth / width);
+ int vpy = Math.round((float) mousey * alheight / sequencesHeight);
- int x = mousex;
- int y = mousey;
+ updateViewportFromTopLeft(vpx + xdiff, vpy + ydiff, hiddenSeqs,
+ hiddenCols);
- if (x < 0)
+ }
+
+ @Override
+ protected void updateViewportFromTopLeft(int leftx, int topy,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
+ {
+ int xAsRes = leftx;
+ int yAsSeq = topy;
+ resetAlignmentDims();
+
+ if (xAsRes < 0)
{
- x = 0;
+ xAsRes = 0;
}
- if (y < 0)
+ if (yAsSeq < 0)
{
- y = 0;
+ yAsSeq = 0;
}
- // Determine where scrollCol should be, given visXAsRes
+ if (ranges.isWrappedMode())
+ {
- y = 0; // sorry, no vertical scroll when wrapped
++ yAsSeq = 0; // sorry, no vertical scroll when wrapped
+ }
- //
- // 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
-
- // convert x to residues - this is an absolute position
- int xAsRes = Math.round((float) x * alwidth / width);
-
// get viewport width in residues
int vpwidth = ranges.getViewportWidth();
}
}
-
- //
- // Convert y value to sequence position
- //
-
- // convert y to residues
- int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
+ // Determine where scrollRow should be, given visYAsSeq
// get viewport height in sequences
// add 1 because height includes both endSeq and startSeq
// update viewport
ranges.setStartRes(xAsRes);
ranges.setStartSeq(yAsSeq);
-
}
@Override
alwidth = ranges.getVisibleAlignmentWidth();
alheight = ranges.getVisibleAlignmentHeight();
}
+
+ @Override
+ protected int getLeftXFromCentreX(int mousex, HiddenColumns hidden)
+ {
+ int vpx = Math.round((float) mousex * alwidth / width);
+ return vpx - ranges.getViewportWidth() / 2;
+ }
+
+ @Override
+ protected int getTopYFromCentreY(int mousey, HiddenSequences hidden)
+ {
+ int vpy = Math.round((float) mousey * alheight / sequencesHeight);
+ return vpy - ranges.getViewportHeight() / 2;
+ }
+
+ @Override
+ public void setDragPoint(int x, int y, HiddenSequences hiddenSeqs,
+ HiddenColumns hiddenCols)
+ {
+ // get alignment position of x and box (can get directly from vpranges) and
+ // calculate difference between the positions
+ int vpx = Math.round((float) x * alwidth / width);
+ int vpy = Math.round((float) y * alheight / sequencesHeight);
+
+ xdiff = ranges.getStartRes() - vpx;
+ ydiff = ranges.getStartSeq() - vpy;
+ }
+
}
{
private ViewportRanges ranges;
+ private int xdiff; // when dragging, difference in alignment units between
+ // start residue and original mouse click position
+
+ private int ydiff; // when dragging, difference in alignment units between
+ // start sequence and original mouse click position
+
/**
* Create an OverviewDimensions object
*
public void updateViewportFromMouse(int mousex, int mousey,
HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
{
- int x = mousex;
- int y = mousey;
+ // convert mousex and mousey to alignment units as well as
+ // translating to top left corner of viewport - this is an absolute position
+ int xAsRes = getLeftXFromCentreX(mousex, hiddenCols);
+ int yAsSeq = getTopYFromCentreY(mousey, hiddenSeqs);
- resetAlignmentDims();
+ // convert to visible positions
+ int visXAsRes = hiddenCols.findColumnPosition(xAsRes);
+ yAsSeq = hiddenSeqs.adjustForHiddenSeqs(
+ hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq));
++ yAsSeq = Math.max(yAsSeq, 0); // -1 if before first visible sequence
+ int visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
++ visYAsSeq = Math.max(visYAsSeq, 0); // -1 if before first visible sequence
- if (x < 0)
- {
- x = 0;
- }
+ // update viewport accordingly
+ updateViewportFromTopLeft(visXAsRes, visYAsSeq, hiddenSeqs, hiddenCols);
+ }
+
+ @Override
+ public void adjustViewportFromMouse(int mousex, int mousey,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
+ {
+ // calculate translation in pixel terms:
+ // get mouse location in viewport coords, add translation in viewport
+ // coords,
+ // convert back to pixel coords
+ int vpx = Math.round((float) mousex * alwidth / width);
+ int visXAsRes = hiddenCols.findColumnPosition(vpx) + xdiff;
+
+ int vpy = Math.round((float) mousey * alheight / sequencesHeight);
+ int visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(vpy) + ydiff;
+
+ // update viewport accordingly
+ updateViewportFromTopLeft(visXAsRes, visYAsRes,
+ hiddenSeqs,
+ hiddenCols);
+ }
+
+ @Override
+ protected void updateViewportFromTopLeft(int leftx, int topy,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
+ {
+ int visXAsRes = leftx;
+ int visYAsSeq = topy;
+ resetAlignmentDims();
- if (y < 0)
+ if (visXAsRes < 0)
{
- y = 0;
+ visXAsRes = 0;
}
- if (ranges.isWrappedMode())
+ if (visYAsSeq < 0)
{
- y = 0; // sorry, no vertical scroll when wrapped
+ visYAsSeq = 0;
}
- //
- // 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
-
- // convert x to residues - this is an absolute position
- int xAsRes = Math.round((float) x * alwidth / width);
+ // Determine where scrollCol should be, given visXAsRes
// get viewport width in residues
int vpwidth = ranges.getViewportWidth();
- // 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)
}
}
- //
- // Convert y value to sequence position
- //
-
- // convert y to residues
- int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
+ // Determine where scrollRow should be, given visYAsSeq
// get viewport height in sequences
int vpheight = ranges.getViewportHeight();
- // 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));
- yAsSeq = Math.max(yAsSeq, 0); // -1 if before first visible sequence
-
// check in case we went off the edge of the alignment
int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
- int visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
- visYAsSeq = Math.max(visYAsSeq, 0); // -1 if before first visible sequence
+
if (visYAsSeq + vpheight - 1 > visAlignHeight)
{
// went past the end of the alignment, adjust backwards
alwidth = ranges.getAbsoluteAlignmentWidth();
alheight = ranges.getAbsoluteAlignmentHeight();
}
+
+ @Override
+ protected int getLeftXFromCentreX(int mousex, HiddenColumns hidden)
+ {
+ int vpx = Math.round((float) mousex * alwidth / width);
+ return hidden.subtractVisibleColumns(ranges.getViewportWidth() / 2,
+ vpx);
+ }
+
+ @Override
+ protected int getTopYFromCentreY(int mousey, HiddenSequences hidden)
+ {
+ int vpy = Math.round((float) mousey * alheight / sequencesHeight);
+ return hidden.subtractVisibleRows(ranges.getViewportHeight() / 2, vpy);
+ }
+
+ @Override
+ public void setDragPoint(int x, int y, HiddenSequences hiddenSeqs,
+ HiddenColumns hiddenCols)
+ {
+ // get alignment position of x and box (can get directly from vpranges) and
+ // calculate difference between the positions
+ int vpx = Math.round((float) x * alwidth / width);
+ int vpy = Math.round((float) y * alheight / sequencesHeight);
+
+ xdiff = ranges.getStartRes() - hiddenCols.findColumnPosition(vpx);
+ ydiff = ranges.getStartSeq()
+ - hiddenSeqs.findIndexWithoutHiddenSeqs(vpy);
+ }
+
}