From: kiramt Date: Sat, 22 Jul 2017 09:18:41 +0000 (+0200) Subject: Merge branch 'develop' into feature/JAL-2611 X-Git-Tag: Release_2_10_3b1~132^2~30^2 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=4a9a2fc8a1b1a66b21e66429083f27a6fc8541b9;hp=-c;p=jalview.git Merge branch 'develop' into feature/JAL-2611 Conflicts: src/jalview/gui/OverviewPanel.java src/jalview/viewmodel/OverviewDimensionsHideHidden.java src/jalview/viewmodel/OverviewDimensionsShowHidden.java --- 4a9a2fc8a1b1a66b21e66429083f27a6fc8541b9 diff --combined src/jalview/appletgui/OverviewPanel.java index 76c4e86,ccdfee1..456a38c --- a/src/jalview/appletgui/OverviewPanel.java +++ b/src/jalview/appletgui/OverviewPanel.java @@@ -29,7 -29,6 +29,7 @@@ import jalview.viewmodel.ViewportListen import java.awt.BorderLayout; import java.awt.CheckboxMenuItem; +import java.awt.Cursor; import java.awt.Dimension; import java.awt.Panel; import java.awt.PopupMenu; @@@ -58,8 -57,6 +58,8 @@@ public class OverviewPanel extends Pane private boolean updateRunning = false; + private boolean draggingBox = false; + public OverviewPanel(AlignmentPanel alPanel) { this.av = alPanel.av; @@@ -121,62 -118,28 +121,62 @@@ @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()) @@@ -186,20 -149,8 +186,20 @@@ } 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); } } @@@ -209,6 -160,14 +209,14 @@@ */ public void updateOverviewImage() { + if (oviewCanvas == null) + { + /* + * panel has been disposed + */ + return; + } + if ((getSize().width > 0) && (getSize().height > 0)) { od.setWidth(getSize().width); @@@ -306,4 -265,21 +314,21 @@@ 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; + } + } } diff --combined src/jalview/datamodel/HiddenSequences.java index ed07290,98e9694..32443d8 --- a/src/jalview/datamodel/HiddenSequences.java +++ b/src/jalview/datamodel/HiddenSequences.java @@@ -157,9 -157,10 +157,10 @@@ public class HiddenSequence 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; @@@ -253,7 -254,8 +254,8 @@@ } /** - * 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 @@@ -310,7 -312,7 +312,7 @@@ return startRow - visibleDistance; } - int index = startRow; + int index = Math.min(startRow, hiddenSequences.length - 1); int count = 0; while ((index > -1) && (count < visibleDistance)) { diff --combined src/jalview/gui/OverviewPanel.java index 1c01108,7a4456e..c81ac2f --- a/src/jalview/gui/OverviewPanel.java +++ b/src/jalview/gui/OverviewPanel.java @@@ -28,7 -28,6 +28,7 @@@ import jalview.viewmodel.OverviewDimens 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; @@@ -66,8 -65,6 +66,8 @@@ public class OverviewPanel extends JPan private boolean showHidden = true; + private boolean draggingBox = false; + /** * Creates a new OverviewPanel object. * @@@ -110,39 -107,11 +110,37 @@@ @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)); } } }); @@@ -159,33 -128,12 +157,34 @@@ 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; } } @@@ -197,8 -145,6 +196,6 @@@ showPopupMenu(evt); } } - - }); updateOverviewImage(); @@@ -258,6 -204,14 +255,14 @@@ */ public void updateOverviewImage() { + if (oviewCanvas == null) + { + /* + * panel has been disposed + */ + return; + } + if ((getWidth() > 0) && (getHeight() > 0)) { od.setWidth(getWidth()); @@@ -274,7 -228,6 +279,6 @@@ Thread thread = new Thread(this); thread.start(); repaint(); - } @Override @@@ -304,4 -257,21 +308,21 @@@ { 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; + } + } } diff --combined src/jalview/viewmodel/OverviewDimensions.java index ee3b511,7ac07ac..f54c1eb --- a/src/jalview/viewmodel/OverviewDimensions.java +++ b/src/jalview/viewmodel/OverviewDimensions.java @@@ -192,44 -192,6 +192,44 @@@ public abstract class OverviewDimension 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 @@@ -263,16 -225,14 +263,17 @@@ */ 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 @@@ -281,31 -241,4 +282,31 @@@ // 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); + } diff --combined src/jalview/viewmodel/OverviewDimensionsHideHidden.java index 7eec343,4d64f1c..c78b8a3 --- a/src/jalview/viewmodel/OverviewDimensionsHideHidden.java +++ b/src/jalview/viewmodel/OverviewDimensionsHideHidden.java @@@ -12,12 -12,6 +12,12 @@@ public class OverviewDimensionsHideHidd { 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) { @@@ -30,48 -24,37 +30,51 @@@ 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(); @@@ -90,7 -73,13 +93,7 @@@ } } - - // - // 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 @@@ -112,6 -101,7 +115,6 @@@ // update viewport ranges.setStartRes(xAsRes); ranges.setStartSeq(yAsSeq); - } @Override @@@ -142,32 -132,4 +145,32 @@@ 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; + } + } diff --combined src/jalview/viewmodel/OverviewDimensionsShowHidden.java index c4b69a8,62e8000..5bd4bba --- a/src/jalview/viewmodel/OverviewDimensionsShowHidden.java +++ b/src/jalview/viewmodel/OverviewDimensionsShowHidden.java @@@ -32,12 -32,6 +32,12 @@@ public class OverviewDimensionsShowHidd { 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 * @@@ -72,64 -66,46 +72,66 @@@ 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) @@@ -148,14 -124,28 +150,14 @@@ } } - // - // 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 @@@ -223,34 -213,4 +225,34 @@@ 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); + } + }