From: kiramt Date: Mon, 15 May 2017 10:42:01 +0000 (+0100) Subject: Merge remote-tracking branch 'origin/develop' into bug/JAL-2491 X-Git-Tag: Release_2_10_2~3^2~64^2~4 X-Git-Url: http://source.jalview.org/gitweb/?p=jalview.git;a=commitdiff_plain;h=c2e5d3d1ebe3b283bdde15637c590721cd6c5637 Merge remote-tracking branch 'origin/develop' into bug/JAL-2491 (not working yet) Conflicts: src/jalview/appletgui/AlignmentPanel.java src/jalview/appletgui/OverviewPanel.java src/jalview/gui/AlignmentPanel.java src/jalview/gui/OverviewPanel.java src/jalview/gui/SeqPanel.java src/jalview/viewmodel/OverviewDimensions.java src/jalview/viewmodel/ViewportRanges.java test/jalview/viewmodel/OverviewDimensionsTest.java --- c2e5d3d1ebe3b283bdde15637c590721cd6c5637 diff --cc src/jalview/appletgui/AlignmentPanel.java index 9753453,458ed54..d95c48f --- a/src/jalview/appletgui/AlignmentPanel.java +++ b/src/jalview/appletgui/AlignmentPanel.java @@@ -684,74 -685,109 +685,75 @@@ public class AlignmentPanel extends Pan } else { - if (vextent + vscroll.getValue() >= av.getAlignment().getHeight()) - { - return false; - } - setScrollValues(hscroll.getValue(), vscroll.getValue() + 1); - } - - repaint(); - return true; - } + int width = av.getAlignment().getWidth(); + int height = av.getAlignment().getHeight(); - public boolean scrollRight(boolean right) - { - if (!right) - { - if (hscroll.getValue() < 1) + if (av.hasHiddenColumns()) { - width = av.getColumnSelection().findColumnPosition(width); - return false; ++ width = av.getAlignment().getHiddenColumns() ++ .findColumnPosition(width); } - setScrollValues(hscroll.getValue() - 1, vscroll.getValue()); - } - else - { - if (hextent + hscroll.getValue() >= av.getAlignment().getWidth()) + if (x < 0) { - return false; + x = 0; } - setScrollValues(hscroll.getValue() + 1, vscroll.getValue()); - } - repaint(); - return true; - } - - public void setScrollValues(int x, int y) - { - int width = av.getAlignment().getWidth(); - int height = av.getAlignment().getHeight(); - - if (av.hasHiddenColumns()) - { - width = av.getAlignment().getHiddenColumns() - .findColumnPosition(width); - } - if (x < 0) - { - x = 0; - } + hextent = seqPanel.seqCanvas.getSize().width / av.getCharWidth(); + vextent = seqPanel.seqCanvas.getSize().height / av.getCharHeight(); + if (hextent > width) + { + hextent = width; + } - hextent = seqPanel.seqCanvas.getSize().width / av.getCharWidth(); - vextent = seqPanel.seqCanvas.getSize().height / av.getCharHeight(); - - if (hextent > width) - { - hextent = width; - } + if (vextent > height) + { + vextent = height; + } - if (vextent > height) - { - vextent = height; - } + if ((hextent + x) > width) + { + System.err.println("hextent was " + hextent + " and x was " + x); - if ((hextent + x) > width) - { - // System.err.println("hextent was " + hextent + " and x was " + x); - // - x = width - hextent; - } + x = width - hextent; + } - if ((vextent + y) > height) - { - y = height - vextent; - } + if ((vextent + y) > height) + { + y = height - vextent; + } - if (y < 0) - { - y = 0; - } + if (y < 0) + { + y = 0; + } - if (x < 0) - { - System.err.println("x was " + x); - x = 0; - } + if (x < 0) + { + System.err.println("x was " + x); + x = 0; + } - vpRanges.setStartSeq(y); - vpRanges.setEndSeq(y + vextent); - vpRanges.setStartRes(x); - vpRanges.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av - .getCharWidth())) - 1); + hscroll.setValues(x, hextent, 0, width); + vscroll.setValues(y, vextent, 0, height); - hscroll.setValues(x, hextent, 0, width); - vscroll.setValues(y, vextent, 0, height); + // AWT scrollbar does not fire adjustmentValueChanged for setValues + // so also call adjustment code! + adjustHorizontal(x); + adjustVertical(y); - if (overviewPanel != null) - { - overviewPanel.setBoxPosition(); + sendViewPosition(); } - sendViewPosition(); - } + /** + * Respond to adjustment event when horizontal or vertical scrollbar is + * changed + * + * @param evt + * adjustment event encoding whether apvscroll, hscroll or vscroll + * changed + */ @Override public void adjustmentValueChanged(AdjustmentEvent evt) { @@@ -979,36 -1045,6 +981,37 @@@ } + /* + * Set vertical scroll bar parameters for wrapped panel + * @param res + * the residue to scroll to + */ + private void setScrollingForWrappedPanel(int res) + { + // get the width of the alignment in residues + int maxwidth = av.getAlignment().getWidth(); + if (av.hasHiddenColumns()) + { - maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1; ++ maxwidth = av.getAlignment().getHiddenColumns() ++ .findColumnPosition(maxwidth) - 1; + } + + // get the width of the canvas in residues + int canvasWidth = seqPanel.seqCanvas + .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width); + if (canvasWidth > 0) + { + // position we want to scroll to is number of canvasWidth's to get there + int current = res / canvasWidth; + + // max scroll position: add one because extent is 1 and scrollbar value + // can only be set to at most max - extent + int max = maxwidth / canvasWidth + 1; + vscroll.setUnitIncrement(1); + vscroll.setValues(current, 1, 0, max); + } + } + protected Panel sequenceHolderPanel = new Panel(); protected Scrollbar vscroll = new Scrollbar(); diff --cc src/jalview/appletgui/OverviewPanel.java index c1b5f9c,b933d30..b3c4a37 --- a/src/jalview/appletgui/OverviewPanel.java +++ b/src/jalview/appletgui/OverviewPanel.java @@@ -20,19 -20,22 +20,23 @@@ */ package jalview.appletgui; - import jalview.datamodel.SequenceI; - import jalview.renderer.seqfeatures.FeatureColourFinder; + import jalview.util.MessageManager; + import jalview.util.Platform; import jalview.viewmodel.OverviewDimensions; + import jalview.viewmodel.OverviewDimensionsHideHidden; + import jalview.viewmodel.OverviewDimensionsShowHidden; +import jalview.viewmodel.ViewportListenerI; - import java.awt.Color; + import java.awt.BorderLayout; + import java.awt.CheckboxMenuItem; import java.awt.Dimension; - import java.awt.Frame; - import java.awt.Graphics; - import java.awt.Image; import java.awt.Panel; + import java.awt.PopupMenu; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; + import java.awt.event.InputEvent; + import java.awt.event.ItemEvent; + import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; @@@ -70,22 -60,15 +62,18 @@@ public class OverviewPanel extends Pane this.av = alPanel.av; this.ap = alPanel; setLayout(null); - nullFrame = new Frame(); - nullFrame.addNotify(); - sr = new SequenceRenderer(av); - sr.graphics = nullFrame.getGraphics(); - sr.renderGaps = false; - sr.forOverview = true; - fr = new FeatureRenderer(av); - - od = new OverviewDimensions(av.getRanges(), + od = new OverviewDimensionsShowHidden(av.getRanges(), (av.isShowAnnotation() && av.getSequenceConsensusHash() != null)); + oviewCanvas = new OverviewCanvas(od, av); + setLayout(new BorderLayout()); + add(oviewCanvas, BorderLayout.CENTER); + setSize(new Dimension(od.getWidth(), od.getHeight())); + + av.getRanges().addPropertyChangeListener(this); + addComponentListener(new ComponentAdapter() { @@@ -148,10 -135,20 +140,19 @@@ private void mouseAction(MouseEvent evt) { - od.updateViewportFromMouse(evt.getX(), evt.getY(), av.getAlignment() - .getHiddenSequences(), av.getColumnSelection(), av - .getRanges()); - ap.paintAlignment(false); + if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) + { + if (!Platform.isAMac()) + { + showPopupMenu(evt); + } + } + else + { + od.updateViewportFromMouse(evt.getX(), evt.getY(), av.getAlignment() + .getHiddenSequences(), av.getAlignment().getHiddenColumns()); - ap.setScrollValues(od.getScrollCol(), od.getScrollRow()); + ap.paintAlignment(false); + } } /** @@@ -336,36 -194,57 +198,63 @@@ * changed * */ - public void setBoxPosition() + private void setBoxPosition() { od.setBoxPosition(av.getAlignment() - .getHiddenSequences(), av.getColumnSelection(), av.getRanges()); + .getHiddenSequences(), av + .getAlignment().getHiddenColumns()); repaint(); } - @Override - public void update(Graphics g) - { - paint(g); - } - - @Override - public void paint(Graphics g) + /* + * Displays the popup menu and acts on user input + */ + private void showPopupMenu(MouseEvent e) { - Graphics og = offscreen.getGraphics(); - if (miniMe != null) + PopupMenu popup = new PopupMenu(); + ItemListener menuListener = new ItemListener() { - og.drawImage(miniMe, 0, 0, this); - og.setColor(Color.red); - od.drawBox(og); - g.drawImage(offscreen, 0, 0, this); - } + @Override + public void itemStateChanged(ItemEvent e) + { + toggleHiddenColumns(); + } + }; + CheckboxMenuItem item = new CheckboxMenuItem( + MessageManager.getString("label.togglehidden")); + item.setState(showHidden); + popup.add(item); + item.addItemListener(menuListener); + this.add(popup); + popup.show(this, e.getX(), e.getY()); } + @Override + public void propertyChange(PropertyChangeEvent evt) + { + setBoxPosition(); + } + + /* + * Toggle overview display between showing hidden columns and hiding hidden columns + */ + private void toggleHiddenColumns() + { + if (showHidden) + { + showHidden = false; + od = new OverviewDimensionsHideHidden(av.getRanges(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null)); + } + else + { + showHidden = true; + od = new OverviewDimensionsShowHidden(av.getRanges(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null)); + } + oviewCanvas.resetOviewDims(od); + updateOverviewImage(); + } } diff --cc src/jalview/appletgui/SeqPanel.java index 76f1275,fcae97c..f5955d1 --- a/src/jalview/appletgui/SeqPanel.java +++ b/src/jalview/appletgui/SeqPanel.java @@@ -228,27 -232,28 +232,28 @@@ public class SeqPanel extends Panel imp else { ViewportRanges ranges = av.getRanges(); + HiddenColumns hidden = av.getAlignment().getHiddenColumns(); while (seqCanvas.cursorY < ranges.getStartSeq()) { - ap.scrollUp(true); + ranges.scrollUp(true); } while (seqCanvas.cursorY + 1 > ranges.getEndSeq()) { - ap.scrollUp(false); + ranges.scrollUp(false); } - while (seqCanvas.cursorX < av.getColumnSelection() - .adjustForHiddenColumns(ranges.getStartRes())) + while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(ranges + .getStartRes())) { - if (!ap.scrollRight(false)) + if (!ranges.scrollRight(false)) { break; } } - while (seqCanvas.cursorX > av.getColumnSelection() - .adjustForHiddenColumns(ranges.getEndRes())) + while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(ranges + .getEndRes())) { - if (!ap.scrollRight(true)) + if (!ranges.scrollRight(true)) { break; } diff --cc src/jalview/gui/AlignmentPanel.java index 0d53172,885d79d..ce9e989 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@@ -660,59 -707,62 +669,59 @@@ public class AlignmentPanel extends GAl { return; } - int width = av.getAlignment().getWidth(); - int height = av.getAlignment().getHeight(); - if (av.hasHiddenColumns()) + if (av.getWrapAlignment()) { - // reset the width to exclude hidden columns - width = av.getAlignment().getHiddenColumns() - .findColumnPosition(width); + setScrollingForWrappedPanel(x); } + else + { + int width = av.getAlignment().getWidth(); + int height = av.getAlignment().getHeight(); - hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth(); - vextent = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight(); + if (av.hasHiddenColumns()) + { + // reset the width to exclude hidden columns - width = av.getColumnSelection().findColumnPosition(width); ++ width = av.getAlignment().getHiddenColumns().findColumnPosition(width); + } - if (hextent > width) - { - hextent = width; - } + hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth(); + vextent = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight(); - if (vextent > height) - { - vextent = height; - } + if (hextent > width) + { + hextent = width; + } - if ((hextent + x) > width) - { - x = width - hextent; - } + if (vextent > height) + { + vextent = height; + } - if ((vextent + y) > height) - { - y = height - vextent; - } + if ((hextent + x) > width) + { + x = width - hextent; + } - if (y < 0) - { - y = 0; - } + if ((vextent + y) > height) + { + y = height - vextent; + } - if (x < 0) - { - x = 0; - } + if (y < 0) + { + y = 0; + } - // update endRes after x has (possibly) been adjusted - vpRanges.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av - .getCharWidth())) - 1); + if (x < 0) + { + x = 0; + } - /* - * each scroll adjustment triggers adjustmentValueChanged, which resets the - * 'do not scroll complement' flag; ensure it is the same for both - * operations - */ - boolean flag = isDontScrollComplement(); - hscroll.setValues(x, hextent, 0, width); - setDontScrollComplement(flag); - vscroll.setValues(y, vextent, 0, height); + // update the scroll values + hscroll.setValues(x, hextent, 0, width); + vscroll.setValues(y, vextent, 0, height); + } } /** @@@ -860,38 -916,37 +869,39 @@@ validate(); /* - * set scroll bar positions; first suppress this being 'followed' in any - * complementary split pane + * set scroll bar positions */ - setDontScrollComplement(true); + setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq()); + } - if (av.getWrapAlignment()) + /* + * Set vertical scroll bar parameters for wrapped panel + * @param res + * the residue to scroll to + */ + private void setScrollingForWrappedPanel(int res) + { + // get the width of the alignment in residues + int maxwidth = av.getAlignment().getWidth(); + if (av.hasHiddenColumns()) { - maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1; - int maxwidth = av.getAlignment().getWidth(); - - if (av.hasHiddenColumns()) - { + maxwidth = av.getAlignment().getHiddenColumns() + .findColumnPosition(maxwidth) - 1; - } - - int canvasWidth = getSeqPanel().seqCanvas - .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth()); - if (canvasWidth > 0) - { - int max = maxwidth - / getSeqPanel().seqCanvas - .getWrappedCanvasWidth(getSeqPanel().seqCanvas - .getWidth()) + 1; - vscroll.setMaximum(max); - vscroll.setUnitIncrement(1); - vscroll.setVisibleAmount(1); - } } - else + + // get the width of the canvas in residues + int canvasWidth = getSeqPanel().seqCanvas + .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth()); + if (canvasWidth > 0) { - setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq()); + // position we want to scroll to is number of canvasWidth's to get there + int current = res / canvasWidth; + + // max scroll position: add one because extent is 1 and scrollbar value + // can only be set to at most max - extent + int max = maxwidth / canvasWidth + 1; + vscroll.setUnitIncrement(1); + vscroll.setValues(current, 1, 0, max); } } @@@ -1868,25 -1934,23 +1894,45 @@@ } } + @Override + /** + * Property change event fired when a change is made to the viewport ranges + * object associated with this alignment panel's viewport + */ + public void propertyChange(PropertyChangeEvent evt) + { + // update this panel's scroll values based on the new viewport ranges values + int x = vpRanges.getStartRes(); + int y = vpRanges.getStartSeq(); + setScrollValues(x, y); + + // now update any complementary alignment (its viewport ranges object + // is different so does not get automatically updated) + if (isSetToScrollComplementPanel()) + { + setToScrollComplementPanel(false); + av.scrollComplementaryAlignment(); + setToScrollComplementPanel(true); + } + } ++ + /** + * Set the reference to the PCA/Tree chooser dialog for this panel. This + * reference should be nulled when the dialog is closed. + * + * @param calculationChooser + */ + public void setCalculationDialog(CalculationChooser calculationChooser) + { + calculationDialog = calculationChooser; + } + + /** + * Returns the reference to the PCA/Tree chooser dialog for this panel (null + * if none is open) + */ + public CalculationChooser getCalculationDialog() + { + return calculationDialog; + } } diff --cc src/jalview/gui/OverviewPanel.java index 095a573,a6c3960..a5441a2 --- a/src/jalview/gui/OverviewPanel.java +++ b/src/jalview/gui/OverviewPanel.java @@@ -20,24 -20,26 +20,28 @@@ */ package jalview.gui; - import jalview.datamodel.SequenceI; - import jalview.renderer.AnnotationRenderer; - import jalview.renderer.seqfeatures.FeatureColourFinder; + import jalview.util.MessageManager; + import jalview.util.Platform; import jalview.viewmodel.OverviewDimensions; + import jalview.viewmodel.OverviewDimensionsHideHidden; + import jalview.viewmodel.OverviewDimensionsShowHidden; +import jalview.viewmodel.ViewportListenerI; - import java.awt.Color; + import java.awt.BorderLayout; import java.awt.Dimension; - import java.awt.Graphics; + import java.awt.event.ActionEvent; + import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; - import java.awt.image.BufferedImage; +import java.beans.PropertyChangeEvent; + import javax.swing.JCheckBoxMenuItem; import javax.swing.JPanel; + import javax.swing.JPopupMenu; + import javax.swing.SwingUtilities; /** * Panel displaying an overview of the full alignment, with an interactive box @@@ -46,18 -48,11 +50,12 @@@ * @author $author$ * @version $Revision$ */ -public class OverviewPanel extends JPanel implements Runnable +public class OverviewPanel extends JPanel implements Runnable, + ViewportListenerI { - private static final Color TRANS_GREY = new Color(100, 100, 100, 25); - - private final AnnotationRenderer renderer = new AnnotationRenderer(); - private OverviewDimensions od; - private BufferedImage miniMe; - - private BufferedImage lastMiniMe = null; + private OverviewCanvas oviewCanvas; private AlignViewport av; @@@ -97,8 -77,10 +80,12 @@@ (av.isShowAnnotation() && av .getAlignmentConservationAnnotation() != null)); + oviewCanvas = new OverviewCanvas(od, av); + setLayout(new BorderLayout()); + add(oviewCanvas, BorderLayout.CENTER); + + av.getRanges().addPropertyChangeListener(this); + addComponentListener(new ComponentAdapter() { @Override @@@ -118,13 -99,13 +105,13 @@@ @Override public void mouseDragged(MouseEvent evt) { - if (!av.getWrapAlignment()) + if (!SwingUtilities.isRightMouseButton(evt) + && !av.getWrapAlignment()) { od.updateViewportFromMouse(evt.getX(), evt.getY(), av - .getAlignment().getHiddenSequences(), av - .getColumnSelection(), av.getRanges()); - // TODO set via ViewportRanges in overview dimensions once JAL-2388 is - // merged + .getAlignment().getHiddenSequences(), av.getAlignment() + .getHiddenColumns()); - ap.setScrollValues(od.getScrollCol(), od.getScrollRow()); ++ } } }); @@@ -134,13 -115,28 +121,27 @@@ @Override public void mousePressed(MouseEvent evt) { - if (!av.getWrapAlignment()) + if (SwingUtilities.isRightMouseButton(evt)) + { + if (!Platform.isAMac()) + { + showPopupMenu(evt); + } + } + else if (!av.getWrapAlignment()) { od.updateViewportFromMouse(evt.getX(), evt.getY(), av - .getAlignment().getHiddenSequences(), av - .getColumnSelection(), av.getRanges()); - // TODO set via ViewportRanges in overview dimensions once JAL-2388 is - // merged + .getAlignment().getHiddenSequences(), av.getAlignment() + .getHiddenColumns()); - ap.setScrollValues(od.getScrollCol(), od.getScrollRow()); + } + } + + @Override + public void mouseClicked(MouseEvent evt) + { + if (SwingUtilities.isRightMouseButton(evt)) + { + showPopupMenu(evt); } } }); @@@ -246,81 -171,60 +176,61 @@@ } /* - * Build the overview panel image + * Toggle overview display between showing hidden columns and hiding hidden columns */ - private void buildImage(float sampleRow, float sampleCol) + private void toggleHiddenColumns() { - int lastcol = -1; - int lastrow = -1; - int rgbColour = Color.white.getRGB(); - - SequenceI seq = null; - FeatureColourFinder finder = new FeatureColourFinder(fr); - - final boolean hasHiddenCols = av.hasHiddenColumns(); - boolean hiddenRow = false; - // get hidden row and hidden column map once at beginning. - // clone featureRenderer settings to avoid race conditions... if state is - // updated just need to refresh again - for (int row = 0; row < od.getSequencesHeight() && !resizeAgain; row++) + if (showHidden) { - boolean doCopy = true; - int currentrow = (int) (row * sampleRow); - if (currentrow != lastrow) - { - doCopy = false; - - lastrow = currentrow; - - // get the sequence which would be at alignment index 'lastrow' if no - // rows were hidden, and determine whether it is hidden or not - hiddenRow = av.getAlignment().isHidden(lastrow); - seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow); - } - - for (int col = 0; col < od.getWidth() && !resizeAgain; col++) - { - if (doCopy) - { - rgbColour = miniMe.getRGB(col, row - 1); - } - else if ((int) (col * sampleCol) != lastcol - || (int) (row * sampleRow) != lastrow) - { - lastcol = (int) (col * sampleCol); - rgbColour = getColumnColourFromSequence(seq, hiddenRow, - hasHiddenCols, lastcol, finder); - } - // else we just use the color we already have , so don't need to set it - - miniMe.setRGB(col, row, rgbColour); - } + showHidden = false; + od = new OverviewDimensionsHideHidden(av.getRanges(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null)); + } + else + { + showHidden = true; + od = new OverviewDimensionsShowHidden(av.getRanges(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null)); } + oviewCanvas.resetOviewDims(od); + updateOverviewImage(); ++ setBoxPosition(); } - /* - * Find the colour of a sequence at a specified column position + /** + * Updates the overview image when the related alignment panel is updated */ - private int getColumnColourFromSequence( - jalview.datamodel.SequenceI seq, - boolean hiddenRow, boolean hasHiddenCols, int lastcol, - FeatureColourFinder finder) + public void updateOverviewImage() { - Color color = Color.white; - - if ((seq != null) && (seq.getLength() > lastcol)) + if ((getWidth() > 0) && (getHeight() > 0)) { - color = sr.getResidueColour(seq, lastcol, finder); + od.setWidth(getWidth()); + od.setHeight(getHeight()); } + + setPreferredSize(new Dimension(od.getWidth(), od.getHeight())); - if (hiddenRow - || (hasHiddenCols && !av.getColumnSelection() - .isVisible(lastcol))) + if (oviewCanvas.restartDraw()) { - color = color.darker().darker(); + return; } - return color.getRGB(); + Thread thread = new Thread(this); + thread.start(); + repaint(); + + } + + @Override + public void run() + { + oviewCanvas.draw(av.isShowSequenceFeatures(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null), ap + .getSeqPanel().seqCanvas.getFeatureRenderer()); + setBoxPosition(); } /** @@@ -328,48 -232,10 +238,16 @@@ * changed * */ - public void setBoxPosition() + private void setBoxPosition() { - od.setBoxPosition(av.getAlignment() - .getHiddenSequences(), av.getColumnSelection(), av.getRanges()); + od.setBoxPosition(av.getAlignment().getHiddenSequences(), av + .getAlignment().getHiddenColumns()); repaint(); } + - - @Override - public void paintComponent(Graphics g) - { - if (resizing || resizeAgain) - { - if (lastMiniMe == null) - { - g.setColor(Color.white); - g.fillRect(0, 0, getWidth(), getHeight()); - } - else - { - g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this); - } - g.setColor(TRANS_GREY); - g.fillRect(0, 0, getWidth(), getHeight()); - } - else if (lastMiniMe != null) - { - g.drawImage(lastMiniMe, 0, 0, this); - if (lastMiniMe != miniMe) - { - g.setColor(TRANS_GREY); - g.fillRect(0, 0, getWidth(), getHeight()); - } - } - - g.setColor(Color.red); - od.drawBox(g); - } - + @Override + public void propertyChange(PropertyChangeEvent evt) + { + setBoxPosition(); + } } diff --cc src/jalview/viewmodel/OverviewDimensions.java index 1b425d4,a837d53..dd7eb1e --- a/src/jalview/viewmodel/OverviewDimensions.java +++ b/src/jalview/viewmodel/OverviewDimensions.java @@@ -25,49 -28,27 +28,44 @@@ import jalview.datamodel.HiddenSequence import java.awt.Graphics; - public class OverviewDimensions + public abstract class OverviewDimensions { - // Default width and height values - private static final int DEFAULT_GRAPH_HEIGHT = 20; + protected static final int MAX_WIDTH = 400; ++ + protected static final int MIN_WIDTH = 120; + - private static final int MAX_WIDTH = 400; + protected static final int MIN_SEQ_HEIGHT = 40; + - private static final int MIN_WIDTH = 120; + protected static final int MAX_SEQ_HEIGHT = 300; - private static final int MIN_SEQ_HEIGHT = 40; + private static final int DEFAULT_GRAPH_HEIGHT = 20; - private static final int MAX_SEQ_HEIGHT = 300; + protected int width; + - // width of the overview panel - private int width; + protected int sequencesHeight; + - // height of sequences part of the overview panel - private int sequencesHeight; + protected int graphHeight = DEFAULT_GRAPH_HEIGHT; + - // height of the graphs part of the overview panel - private int graphHeight = DEFAULT_GRAPH_HEIGHT; + protected int boxX = -1; + - // dimensions of box outlining current extent of view in alignment panel - // location of left side of box - private int boxX = -1; + protected int boxY = -1; + - // location of bottom of box - private int boxY = -1; + protected int boxWidth = -1; + - // width of box - private int boxWidth = -1; + protected int boxHeight = -1; - protected int scrollCol = -1; - protected int scrollRow = -1; + - // height of box - private int boxHeight = -1; + protected int alwidth; ++ + protected int alheight; + /** + * 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) { @@@ -267,8 -97,16 +114,6 @@@ g.drawRect(boxX + 1, boxY + 1, boxWidth - 2, boxHeight - 2); } - // TODO should be removed, when unit test has mock Graphics object available - // to check boxX/boxY - public int getScrollCol() - { - return scrollCol; - } - - public int getScrollRow() - { - return scrollRow; - } - public int getBoxX() { return boxX; diff --cc src/jalview/viewmodel/OverviewDimensionsHideHidden.java index 0000000,b03f9ac..9236151 mode 000000,100644..100644 --- a/src/jalview/viewmodel/OverviewDimensionsHideHidden.java +++ b/src/jalview/viewmodel/OverviewDimensionsHideHidden.java @@@ -1,0 -1,137 +1,137 @@@ + package jalview.viewmodel; + + import jalview.api.AlignmentColsCollectionI; + import jalview.api.AlignmentRowsCollectionI; + import jalview.datamodel.AlignmentI; + import jalview.datamodel.HiddenColumns; + import jalview.datamodel.HiddenSequences; + import jalview.datamodel.VisibleColsCollection; + import jalview.datamodel.VisibleRowsCollection; + + public class OverviewDimensionsHideHidden extends OverviewDimensions + { + private ViewportRanges ranges; + + public OverviewDimensionsHideHidden(ViewportRanges vpranges, + boolean showAnnotationPanel) + { + super(vpranges, showAnnotationPanel); + ranges = vpranges; + resetAlignmentDims(); + } + + @Override + public void updateViewportFromMouse(int mousex, int mousey, + HiddenSequences hiddenSeqs, HiddenColumns hiddenCols) + { + resetAlignmentDims(); + + int x = mousex; + int y = mousey; + + if (x < 0) + { + x = 0; + } + + if (y < 0) + { + y = 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); + + // get viewport width in residues - int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1; ++ int vpwidth = ranges.getViewportWidth(); + + if (xAsRes + vpwidth > alwidth) + { + // 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) < alwidth) ++ if ((ranges.getEndRes() + vpwidth - 1) < alwidth) + { + xAsRes = alwidth - vpwidth; + } + else + { - xAsRes = scrollCol; ++ xAsRes = ranges.getEndRes(); + } + } + + + // + // Convert y value to sequence position + // + + // convert y to residues + int yAsSeq = Math.round((float) y * alheight / sequencesHeight); + + // get viewport height in sequences + // add 1 because height includes both endSeq and startSeq - int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1; ++ int vpheight = ranges.getViewportHeight(); + + if (yAsSeq + vpheight > alheight) + { + // went past the end of the alignment, adjust backwards - if ((scrollRow + vpheight - 1) < alheight) ++ if ((ranges.getEndSeq() + vpheight - 1) < alheight) + { + yAsSeq = alheight - vpheight; + } + else + { - yAsSeq = scrollRow; ++ yAsSeq = ranges.getEndSeq(); + } + } + - // update scroll values - scrollCol = xAsRes; - scrollRow = yAsSeq; ++ // update viewport ++ ranges.setStartRes(xAsRes); ++ ranges.setStartSeq(yAsSeq); + + } + + @Override + public void setBoxPosition(HiddenSequences hiddenSeqs, + HiddenColumns hiddenCols) + { + // work with visible values of startRes and endRes + int startRes = ranges.getStartRes(); + int endRes = ranges.getEndRes(); + + // work with visible values of startSeq and endSeq + int startSeq = ranges.getStartSeq(); + int endSeq = ranges.getEndSeq(); + + setBoxPosition(startRes, endRes, startSeq, endSeq); + } + + @Override + public AlignmentColsCollectionI getColumns(AlignmentI al) + { + return new VisibleColsCollection(0, + ranges.getAbsoluteAlignmentWidth() - 1, al); + } + + @Override + public AlignmentRowsCollectionI getRows(AlignmentI al) + { + return new VisibleRowsCollection(0, + ranges.getAbsoluteAlignmentHeight() - 1, al); + } + + @Override + protected void resetAlignmentDims() + { + alwidth = ranges.getVisibleAlignmentWidth(); + alheight = ranges.getVisibleAlignmentHeight(); + } + } diff --cc src/jalview/viewmodel/OverviewDimensionsShowHidden.java index 0000000,b897189..4f7d6c2 mode 000000,100644..100644 --- a/src/jalview/viewmodel/OverviewDimensionsShowHidden.java +++ b/src/jalview/viewmodel/OverviewDimensionsShowHidden.java @@@ -1,0 -1,211 +1,210 @@@ + /* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ + package jalview.viewmodel; + + import jalview.api.AlignmentColsCollectionI; + import jalview.api.AlignmentRowsCollectionI; + import jalview.datamodel.AlignmentI; + import jalview.datamodel.AllColsCollection; + import jalview.datamodel.AllRowsCollection; + import jalview.datamodel.HiddenColumns; + import jalview.datamodel.HiddenSequences; + + public class OverviewDimensionsShowHidden extends OverviewDimensions + { + private ViewportRanges ranges; + + /** + * 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 OverviewDimensionsShowHidden(ViewportRanges vpranges, + boolean showAnnotationPanel) + { + super(vpranges, showAnnotationPanel); + ranges = vpranges; + resetAlignmentDims(); + } + + /** + * 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 ranges + * viewport position properties + */ + @Override + public void updateViewportFromMouse(int mousex, int mousey, + HiddenSequences hiddenSeqs, HiddenColumns hiddenCols) + { + int x = mousex; + int y = mousey; + + resetAlignmentDims(); + + if (x < 0) + { + x = 0; + } + + if (y < 0) + { + y = 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); + + // get viewport width in residues - int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1; ++ 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) + { + // 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) ++ if ((ranges.getEndRes() + vpwidth - 1) < visAlignWidth) + { + visXAsRes = hiddenCols.findColumnPosition(hiddenCols + .subtractVisibleColumns(vpwidth - 1, alwidth - 1)); + } + else + { - visXAsRes = scrollCol; ++ visXAsRes = ranges.getEndRes(); + } + } + + // + // Convert y value to sequence position + // + + // convert y to residues + int yAsSeq = Math.round((float) y * alheight / sequencesHeight); + + // get viewport height in sequences - // add 1 because height includes both endSeq and startSeq - int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1; ++ 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)); + + // check in case we went off the edge of the alignment + int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight); + int visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq); + if (visYAsSeq + vpheight - 1 > visAlignHeight) + { + // went past the end of the alignment, adjust backwards - if ((scrollRow + vpheight - 1) < visAlignHeight) ++ if ((ranges.getEndSeq() + vpheight - 1) < visAlignHeight) + { + visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs + .subtractVisibleRows(vpheight - 1, alheight - 1)); + } + else + { - visYAsSeq = scrollRow; ++ visYAsSeq = ranges.getEndSeq(); + } + } + - // update scroll values - scrollCol = visXAsRes; - scrollRow = visYAsSeq; ++ // update viewport ++ ranges.setStartRes(xAsRes); ++ ranges.setStartSeq(yAsSeq); + + } + + /** + * Update the overview panel box when the associated alignment panel is + * changed + * + * @param hiddenSeqs + * hidden sequences + * @param hiddenCols + * hidden columns + * @param ranges + * viewport position properties + */ + @Override + public void setBoxPosition(HiddenSequences hiddenSeqs, + HiddenColumns hiddenCols) + { + // work with absolute values of startRes and endRes + int startRes = hiddenCols + .adjustForHiddenColumns(ranges.getStartRes()); + int endRes = hiddenCols.adjustForHiddenColumns(ranges.getEndRes()); + + // work with absolute values of startSeq and endSeq + int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq()); + int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq()); + + setBoxPosition(startRes, endRes, startSeq, endSeq); + } + + @Override + public AlignmentColsCollectionI getColumns(AlignmentI al) + { + return new AllColsCollection(0, + ranges.getAbsoluteAlignmentWidth() - 1, al); + } + + @Override + public AlignmentRowsCollectionI getRows(AlignmentI al) + { + return new AllRowsCollection(0, + ranges.getAbsoluteAlignmentHeight() - 1, + al); + } + + @Override + protected void resetAlignmentDims() + { + alwidth = ranges.getAbsoluteAlignmentWidth(); + alheight = ranges.getAbsoluteAlignmentHeight(); + } + } diff --cc src/jalview/viewmodel/ViewportRanges.java index ac310cc,fc163e0..da39e36 --- a/src/jalview/viewmodel/ViewportRanges.java +++ b/src/jalview/viewmodel/ViewportRanges.java @@@ -20,14 -20,13 +20,15 @@@ */ package jalview.viewmodel; +import jalview.api.AlignViewportI; import jalview.datamodel.AlignmentI; ++import jalview.datamodel.HiddenColumns; /** - * Embryonic class which: Supplies and updates viewport properties relating to - * position such as: start and end residues and sequences; ideally will serve - * hidden columns/rows too. Intention also to support calculations for - * positioning, scrolling etc. such as finding the middle of the viewport, + * Slightly less embryonic class which: Supplies and updates viewport properties + * relating to position such as: start and end residues and sequences; ideally + * will serve hidden columns/rows too. Intention also to support calculations + * for positioning, scrolling etc. such as finding the middle of the viewport, * checking for scrolls off screen */ public class ViewportRanges extends ViewportProperties @@@ -80,8 -79,23 +81,24 @@@ } /** + * Get alignment width in cols, excluding hidden cols + */ + public int getVisibleAlignmentWidth() + { + return al.getWidth() - al.getHiddenColumns().getSize(); + } + + /** + * Get alignment height in rows, excluding hidden rows + */ + public int getVisibleAlignmentHeight() + { + return al.getHeight(); + } + + /** - * Set first residue visible in the viewport + * Set first residue visible in the viewport, and retain the current width. + * Fires a property change event. * * @param res * residue position @@@ -266,230 -201,4 +283,231 @@@ { return endSeq; } + + /** + * Set viewport width in residues, without changing startRes. Use in + * preference to calculating endRes from the width, to avoid out by one + * errors! Fires a property change event. + * + * @param w + * width in residues + */ + public void setViewportWidth(int w) + { + setStartEndRes(startRes, startRes + w - 1); + } + + /** + * Set viewport height in residues, without changing startSeq. Use in + * preference to calculating endSeq from the height, to avoid out by one + * errors! Fires a property change event. + * + * @param h + * height in sequences + */ + public void setViewportHeight(int h) + { + setStartEndSeq(startSeq, startSeq + h - 1); + } + + /** + * Set viewport horizontal start position and width. Use in preference to + * calculating endRes from the width, to avoid out by one errors! Fires a + * property change event. + * + * @param start + * start residue + * @param w + * width in residues + */ + public void setViewportStartAndWidth(int start, int w) + { + int vpstart = start; + if (vpstart < 0) + { + vpstart = 0; + } + else if (vpstart + w - 1 > al.getWidth() - 1) + { + vpstart = al.getWidth() - 1; + } + setStartEndRes(vpstart, vpstart + w - 1); + } + + /** + * Set viewport vertical start position and height. Use in preference to + * calculating endSeq from the height, to avoid out by one errors! Fires a + * property change event. + * + * @param start + * start sequence + * @param h + * height in sequences + */ + public void setViewportStartAndHeight(int start, int h) + { + int vpstart = start; + if (vpstart < 0) + { + vpstart = 0; + } + else if (vpstart + h - 1 > al.getHeight() - 1) + { + vpstart = al.getHeight() - h; + } + setStartEndSeq(vpstart, vpstart + h - 1); + } + + /** + * Get width of viewport in residues + * + * @return width of viewport + */ + public int getViewportWidth() + { + return (endRes - startRes + 1); + } + + /** + * Get height of viewport in residues + * + * @return height of viewport + */ + public int getViewportHeight() + { + return (endSeq - startSeq + 1); + } + + /** + * Scroll the viewport range vertically. Fires a property change event. + * + * @param up + * true if scrolling up, false if down + * + * @return true if the scroll is valid + */ + public boolean scrollUp(boolean up) + { + if (up) + { + if (startSeq < 1) + { + return false; + } + + setStartSeq(startSeq - 1); + } + else + { + if (endSeq >= al.getHeight() - 1) + { + return false; + } + + setStartSeq(startSeq + 1); + } + return true; + } + + /** + * Scroll the viewport range horizontally. Fires a property change event. + * + * @param right + * true if scrolling right, false if left + * + * @return true if the scroll is valid + */ + public boolean scrollRight(boolean right) + { + if (!right) + { + if (startRes < 1) + { + return false; + } + + setStartRes(startRes - 1); + } + else + { + if (endRes > al.getWidth() - 1) + { + return false; + } + + setStartRes(startRes + 1); + } + + return true; + } + + /** + * Scroll a wrapped alignment so that the specified residue is visible. Fires + * a property change event. + * + * @param res + * residue position to scroll to + */ + public void scrollToWrappedVisible(int res) + { + // get the start residue of the wrapped row which res is in + // and set that as our start residue + int width = getViewportWidth(); + setStartRes((res / width) * width); + } + + /** + * Scroll so that (x,y) is visible. Fires a property change event. + * + * @param x + * x position in alignment + * @param y + * y position in alignment + * @param av + * viewport to be visible in. Here until hidden columns JAL-2388 + * merged, then use alignment to get hidden cols + */ + public void scrollToVisible(int x, int y, AlignViewportI av) + { + while (y < startSeq) + { + scrollUp(true); + } + while (y > endSeq) + { + scrollUp(false); + } + - while (x < av.getColumnSelection().adjustForHiddenColumns(startRes)) ++ HiddenColumns hidden = al.getHiddenColumns(); ++ while (x < hidden.adjustForHiddenColumns(startRes)) + { + if (!scrollRight(false)) + { + break; + } + } - while (x > av.getColumnSelection().adjustForHiddenColumns(endRes)) ++ while (x > hidden.adjustForHiddenColumns(endRes)) + { + if (!scrollRight(true)) + { + break; + } + } + } + + /** + * Adjust sequence position for page up. Fires a property change event. + */ + public void pageUp() + { + setViewportStartAndHeight(2 * startSeq - endSeq, getViewportHeight()); + } + + /** + * Adjust sequence position for page down. Fires a property change event. + */ + public void pageDown() + { + setViewportStartAndHeight(endSeq, getViewportHeight()); + } } diff --cc test/jalview/viewmodel/OverviewDimensionsHideHiddenTest.java index 0000000,2bd9c47..0e931eb mode 000000,100644..100644 --- a/test/jalview/viewmodel/OverviewDimensionsHideHiddenTest.java +++ b/test/jalview/viewmodel/OverviewDimensionsHideHiddenTest.java @@@ -1,0 -1,989 +1,982 @@@ + /* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ + package jalview.viewmodel; + + import static org.testng.Assert.assertEquals; + + import jalview.analysis.AlignmentGenerator; + import jalview.datamodel.Alignment; + import jalview.datamodel.AlignmentI; + import jalview.datamodel.ColumnSelection; + import jalview.datamodel.HiddenColumns; + import jalview.datamodel.Sequence; + import jalview.datamodel.SequenceCollectionI; + import jalview.datamodel.SequenceGroup; + import jalview.datamodel.SequenceI; + + import java.util.Hashtable; + + import org.testng.annotations.AfterClass; + import org.testng.annotations.BeforeClass; + import org.testng.annotations.BeforeMethod; + import org.testng.annotations.Test; + + @Test(singleThreaded = true) + public class OverviewDimensionsHideHiddenTest + { + AlignmentI al; + + OverviewDimensionsHideHidden od; + + // cached widths and heights + int boxWidth; + int boxHeight; + int viewHeight; + int viewWidth; + int alheight; + int alwidth; + + ViewportRanges vpranges; + + Hashtable hiddenRepSequences = new Hashtable(); + + HiddenColumns hiddenCols = new HiddenColumns(); + + @BeforeClass(alwaysRun = true) + public void setUpAlignment() + { + // create random alignment + AlignmentGenerator gen = new AlignmentGenerator(false); + al = gen.generate(157, 525, 123, 5, 5); + } + + @BeforeMethod(alwaysRun = true) + public void setUp() + { + if (!hiddenRepSequences.isEmpty()) + { + al.getHiddenSequences().showAll(hiddenRepSequences); + } + ColumnSelection colsel = new ColumnSelection(); + hiddenCols.revealAllHiddenColumns(colsel); + + vpranges = new ViewportRanges(al); - vpranges.setStartRes(0); - vpranges.setEndRes(62); - vpranges.setStartSeq(0); - vpranges.setEndSeq(17); ++ vpranges.setViewportStartAndHeight(0, 18); ++ vpranges.setViewportStartAndWidth(0, 63); + + viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1; + viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1; + + HiddenColumns hiddenCols = new HiddenColumns(); + + od = new OverviewDimensionsHideHidden(vpranges, true); + // Initial box sizing - default path through code + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + + mouseClick(od, 0, 0); + moveViewport(0, 0); + + // calculate with visible values + alheight = vpranges.getVisibleAlignmentHeight(); + alwidth = vpranges.getVisibleAlignmentWidth(); + + boxWidth = Math.round((float) (vpranges.getEndRes() + - vpranges.getStartRes() + 1) + * od.getWidth() / alwidth); + boxHeight = Math.round((float) (vpranges.getEndSeq() + - vpranges.getStartSeq() + 1) + * od.getSequencesHeight() / alheight); + } + + @AfterClass(alwaysRun = true) + public void cleanUp() + { + al = null; + } + + /** + * Test that the OverviewDimensions constructor sets width and height + * correctly + */ + @Test(groups = { "Functional" }) + public void testConstructor() + { + SequenceI seqa = new Sequence("Seq1", "ABC"); + SequenceI seqb = new Sequence("Seq2", "ABC"); + SequenceI seqc = new Sequence("Seq3", "ABC"); + SequenceI seqd = new Sequence("Seq4", "ABC"); + SequenceI seqe = new Sequence("Seq5", + "ABCABCABCABCABCABCABCABCBACBACBACBAC"); + + int defaultGraphHeight = 20; + int maxWidth = 400; + int minWidth = 120; + int maxSeqHeight = 300; + int minSeqHeight = 40; + + // test for alignment with width > height + SequenceI[] seqs1 = new SequenceI[] { seqa, seqb }; + Alignment al1 = new Alignment(seqs1); + ViewportRanges props = new ViewportRanges(al1); + + OverviewDimensions od = new OverviewDimensionsHideHidden(props, true); + int scaledHeight = 267; + assertEquals(od.getGraphHeight(), defaultGraphHeight); + assertEquals(od.getSequencesHeight(), scaledHeight); + assertEquals(od.getWidth(), maxWidth); + assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight); + + // test for alignment with width < height + SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd }; + Alignment al2 = new Alignment(seqs2); + props = new ViewportRanges(al2); + + od = new OverviewDimensionsHideHidden(props, true); + int scaledWidth = 300; + assertEquals(od.getGraphHeight(), defaultGraphHeight); + assertEquals(od.getSequencesHeight(), maxSeqHeight); + assertEquals(od.getWidth(), scaledWidth); + assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight); + + // test for alignment with width > height and sequence height scaled below + // min value + SequenceI[] seqs3 = new SequenceI[] { seqe }; + Alignment al3 = new Alignment(seqs3); + props = new ViewportRanges(al3); + + od = new OverviewDimensionsHideHidden(props, true); + assertEquals(od.getGraphHeight(), defaultGraphHeight); + assertEquals(od.getSequencesHeight(), minSeqHeight); + assertEquals(od.getWidth(), maxWidth); + assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight); + + // test for alignment with width < height and width scaled below min value + SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa, + seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd }; + Alignment al4 = new Alignment(seqs4); + props = new ViewportRanges(al4); + + od = new OverviewDimensionsHideHidden(props, true); + assertEquals(od.getGraphHeight(), defaultGraphHeight); + assertEquals(od.getSequencesHeight(), maxSeqHeight); + assertEquals(od.getWidth(), minWidth); + assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight); + + Alignment al5 = new Alignment(seqs4); + props = new ViewportRanges(al5); + + od = new OverviewDimensionsHideHidden(props, false); + assertEquals(od.getGraphHeight(), 0); + assertEquals(od.getSequencesHeight(), maxSeqHeight); + assertEquals(od.getWidth(), minWidth); + assertEquals(od.getHeight(), maxSeqHeight); + } + + /** + * Test that validation after mouse adjustments to boxX and boxY sets box + * dimensions and scroll values correctly, when there are no hidden rows or + * columns. + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromMouseClick() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // negative boxX value reset to 0 + mouseClick(od, -5, 10); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollRow(), ++ assertEquals(vpranges.getStartSeq(), + Math.round((float) 10 * alheight / od.getSequencesHeight())); - assertEquals(od.getScrollCol(), 0); ++ assertEquals(vpranges.getStartRes(), 0); + + // negative boxY value reset to 0 + mouseClick(od, 6, -2); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) 6 * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // overly large boxX value reset to width-boxWidth + mouseClick(od, 100, 6); + assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth()); + assertEquals(od.getBoxY(), 6); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight())); + + // overly large boxY value reset to sequenceHeight - boxHeight + mouseClick(od, 10, 520); + assertEquals(od.getBoxX(), 10); + assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight()); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); + + // here (float) od.getBoxY() * alheight / od.getSequencesHeight() = 507.5 + // and round rounds to 508; however we get 507 working with row values + // hence the subtraction of 1 - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight()) - 1); + + // click past end of alignment, as above + mouseClick(od, 3000, 5); + assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth()); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight())); + + // move viewport so startRes non-zero and then mouseclick + moveViewportH(50); + + // click at viewport position + int oldboxx = od.getBoxX(); + int oldboxy = od.getBoxY(); + mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2); + assertEquals(od.getBoxX(), oldboxx + 5); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); + assertEquals(od.getBoxY(), oldboxy + 2); - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight())); + + // click at top corner + mouseClick(od, 0, 0); + assertEquals(od.getBoxX(), 0); - assertEquals(od.getScrollCol(), 0); ++ assertEquals(vpranges.getStartRes(), 0); + assertEquals(od.getBoxY(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test setting of the box position, when there are hidden cols at the start + * of the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenColsAtStart() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide cols at start and check updated box position is correct + int lastHiddenCol = 30; + hiddenCols.hideColumns(0, lastHiddenCol); + + testBoxIsAtClickPoint(0, 0); + + // click to right of hidden columns, box moves to click point + testBoxIsAtClickPoint(40, 0); - assertEquals(od.getScrollRow(), 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartSeq(), 0); ++ assertEquals(vpranges.getStartRes(), + Math.round((float) 40 * alwidth / od.getWidth())); + + // click to right of hidden columns such that box runs over right hand side + // of alignment + // box position is adjusted away from the edge + // overly large boxX value reset to width-boxWidth + int xpos = 100; + mouseClick(od, xpos, 0); + assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + } + + /** + * Test setting of the box position, when there are hidden cols in the middle + * of the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenColsInMiddle() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + testBoxIsAtClickPoint(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide columns 63-73, no change to box position or dimensions + int firstHidden = 63; + int lastHidden = 73; + hiddenCols.hideColumns(firstHidden, lastHidden); + + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + testBoxIsAtClickPoint(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // move box so that it overlaps with hidden cols on one side + // box width, boxX and scrollCol as for unhidden case + int xpos = 55 - boxWidth; // 55 is position in overview approx halfway + // between cols 60 and 70 + mouseClick(od, xpos, 0); + testBoxIsAtClickPoint(xpos, 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round(xpos * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // move box so that it completely covers hidden cols + // box width, boxX and scrollCol as for unhidden case + xpos = 33; + mouseClick(od, xpos, 0); + testBoxIsAtClickPoint(xpos, 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) xpos * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // move box so boxX is in hidden cols, box overhangs at right + // boxX and scrollCol at left of hidden area, box width unchanged + xpos = 50; + mouseClick(od, xpos, 0); + testBoxIsAtClickPoint(xpos, 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) xpos * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // move box so boxX is to right of hidden cols, but does not go beyond full + // width of alignment + // box width, boxX and scrollCol all as for non-hidden case + xpos = 75; + testBoxIsAtClickPoint(xpos, 0); - assertEquals(od.getScrollRow(), 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartSeq(), 0); ++ assertEquals(vpranges.getStartRes(), + Math.round(xpos * alwidth / od.getWidth())); + + // move box so it goes beyond full width of alignment + // boxX, scrollCol adjusted back, box width normal + xpos = 3000; + mouseClick(od, xpos, 0); + assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + } + + /** + * Test setting of the box position, when there are hidden cols at the end of + * the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenColsAtEnd() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide columns 140-164, no change to box position or dimensions + int firstHidden = 140; + int lastHidden = 164; + hiddenCols.hideColumns(firstHidden, lastHidden); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // click to left of hidden cols, without overlapping + // boxX, scrollCol and width as normal + int xpos = 5; + testBoxIsAtClickPoint(xpos, 0); - assertEquals(od.getScrollRow(), 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartSeq(), 0); ++ assertEquals(vpranges.getStartRes(), + Math.round((float) xpos * alwidth / od.getWidth())); + + // click to left of hidden cols, with overlap + // boxX and scrollCol adjusted for hidden cols, width normal + xpos = Math.round((float) 145 * od.getWidth() / alwidth) - boxWidth; + mouseClick(od, xpos, 0); + testBoxIsAtClickPoint(xpos, 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) xpos * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // click off end of alignment + // boxX and scrollCol adjusted backwards, width normal + xpos = 3000; + mouseClick(od, xpos, 0); + assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + } + + /** + * Test that the box position is set correctly when set from the viewport, + * with no hidden rows or columns + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewport() + { + // move viewport to start of alignment + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to right + moveViewportH(70); + assertEquals(od.getBoxX(), + Math.round((float) 70 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport down + moveViewportV(100); + assertEquals(od.getBoxX(), + Math.round((float) 70 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), + Math.round(100 * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to bottom right + moveViewport(98, 508); + assertEquals(od.getBoxX(), + Math.round((float) 98 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), + Math.round((float) 508 * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden columns + * at the start + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenColsAtStart() + { + int firstHidden = 0; + int lastHidden = 20; + hiddenCols.hideColumns(firstHidden, lastHidden); + + // move viewport to start of alignment + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to end of alignment - need to make startRes by removing + // hidden cols because of how viewport/overview are implemented + moveViewport(98 - lastHidden - 1, 0); + assertEquals(od.getBoxX(), + Math.round((float) (98 - lastHidden - 1) * od.getWidth() + / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden columns + * in the middle + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenColsInMiddle() + { + int firstHidden = 68; + int lastHidden = 78; + hiddenCols.hideColumns(firstHidden, lastHidden); + + // move viewport before hidden columns + moveViewport(3, 0); + + assertEquals(od.getBoxX(), + Math.round((float) 3 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to left of hidden columns with overlap + moveViewport(10, 0); + assertEquals(od.getBoxX(), + Math.round((float) 10 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to straddle hidden columns + moveViewport(63, 0); + assertEquals(od.getBoxX(), + Math.round((float) 63 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to right of hidden columns, no overlap + moveViewport(80 - (lastHidden - firstHidden + 1), 0); + assertEquals(od.getBoxX(), + Math.round((float) (80 - (lastHidden - firstHidden + 1)) + * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + } + + /** + * Test that the box position is set correctly when there are hidden columns + * at the end + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenColsAtEnd() + { + int firstHidden = 152; + int lastHidden = 164; + hiddenCols.hideColumns(firstHidden, lastHidden); + + // move viewport before hidden columns + moveViewport(3, 0); + assertEquals(od.getBoxX(), + Math.round((float) 3 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to hidden columns + // viewport can't actually extend into hidden cols, + // so move to the far right edge of the viewport + moveViewport(firstHidden - viewWidth, 0); + assertEquals(od.getBoxX(), + Math.round((float) (firstHidden - viewWidth) + * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden rows at + * the start + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenRowsAtStart() + { + int firstHidden = 0; + int lastHidden = 20; + hideSequences(firstHidden, lastHidden); + + // calculate with visible values + alheight = vpranges.getVisibleAlignmentHeight(); + alwidth = vpranges.getVisibleAlignmentWidth(); + + boxWidth = Math.round((float) (vpranges.getEndRes() + - vpranges.getStartRes() + 1) + * od.getWidth() / alwidth); + boxHeight = Math.round((float) (vpranges.getEndSeq() + - vpranges.getStartSeq() + 1) + * od.getSequencesHeight() / alheight); + + // move viewport to start of alignment: + // box moves to below hidden rows, height remains same + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to end of alignment + moveViewport(0, 525 - viewHeight - lastHidden - 1); + assertEquals(od.getBoxX(), 0); + assertEquals( + od.getBoxY(), + Math.round((float) (525 - viewHeight - lastHidden - 1) + * od.getSequencesHeight() + / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden rows in + * the middle + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenRowsInMiddle() + { + int firstHidden = 200; + int lastHidden = 210; + hideSequences(firstHidden, lastHidden); + + // calculate with visible values + alheight = vpranges.getVisibleAlignmentHeight(); + alwidth = vpranges.getVisibleAlignmentWidth(); + + boxWidth = Math.round((float) (vpranges.getEndRes() + - vpranges.getStartRes() + 1) + * od.getWidth() / alwidth); + boxHeight = Math.round((float) (vpranges.getEndSeq() + - vpranges.getStartSeq() + 1) + * od.getSequencesHeight() / alheight); + + // move viewport to start of alignment: + // box, height etc as in non-hidden case + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to straddle hidden rows + moveViewport(0, 198); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), Math.round ((float)198 * od.getSequencesHeight() + / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden rows at + * the bottom + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenRowsAtEnd() + { + int firstHidden = 500; + int lastHidden = 524; + hideSequences(firstHidden, lastHidden); + + // calculate with visible values + alheight = vpranges.getVisibleAlignmentHeight(); + alwidth = vpranges.getVisibleAlignmentWidth(); + + boxWidth = Math.round((float) (vpranges.getEndRes() + - vpranges.getStartRes() + 1) + * od.getWidth() / alwidth); + boxHeight = Math.round((float) (vpranges.getEndSeq() + - vpranges.getStartSeq() + 1) + * od.getSequencesHeight() / alheight); + + // move viewport to start of alignment: + // box, height etc as in non-hidden case + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to end of alignment + // viewport sits above hidden rows and does not include them + moveViewport(0, firstHidden - viewHeight - 1); + assertEquals(od.getBoxX(), 0); + assertEquals( + od.getBoxY(), + Math.round((float) (firstHidden - viewHeight - 1) + * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + } + + /** + * Test setting of the box position, when there are hidden rows at the start + * of the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenRowsAtStart() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxHeight(), boxHeight); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide rows at start and check updated box position is correct + int lastHiddenRow = 30; + hideSequences(0, lastHiddenRow); + + // calculate with visible values + alheight = vpranges.getVisibleAlignmentHeight(); + alwidth = vpranges.getVisibleAlignmentWidth(); + + boxWidth = Math.round((float) (vpranges.getEndRes() + - vpranges.getStartRes() + 1) + * od.getWidth() / alwidth); + boxHeight = Math.round((float) (vpranges.getEndSeq() + - vpranges.getStartSeq() + 1) + * od.getSequencesHeight() / alheight); + + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click below hidden rows + mouseClick(od, 0, 150); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 150); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test setting of the box position, when there are hidden rows at the middle + * of the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenRowsInMiddle() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide rows in middle and check updated box position is correct + // no changes + int firstHiddenRow = 50; + int lastHiddenRow = 54; + hideSequences(firstHiddenRow, lastHiddenRow); + + // calculate with visible values + alheight = vpranges.getVisibleAlignmentHeight(); + alwidth = vpranges.getVisibleAlignmentWidth(); + + boxWidth = Math.round((float) (vpranges.getEndRes() + - vpranges.getStartRes() + 1) + * od.getWidth() / alwidth); + boxHeight = Math.round((float) (vpranges.getEndSeq() + - vpranges.getStartSeq() + 1) + * od.getSequencesHeight() / alheight); + + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click above hidden rows, so that box overlaps + int ypos = 35; // column value in residues + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click so that box straddles hidden rows + ypos = 44; // column value in residues + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test setting of the box position, when there are hidden rows at the end of + * the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenRowsAtEnd() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide rows at end and check updated box position is correct + // no changes + int firstHidden = 500; + int lastHidden = 524; + hideSequences(firstHidden, lastHidden); + + // calculate with visible values + alheight = vpranges.getVisibleAlignmentHeight(); + alwidth = vpranges.getVisibleAlignmentWidth(); + + boxWidth = Math.round((float) (vpranges.getEndRes() + - vpranges.getStartRes() + 1) + * od.getWidth() / alwidth); + boxHeight = Math.round((float) (vpranges.getEndSeq() + - vpranges.getStartSeq() + 1) + * od.getSequencesHeight() / alheight); + + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click above hidden rows + int ypos = 40; // row 40 + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click above hidden rows so box overlaps + // boxY, boxHeight remains same + ypos = 497; // row 497 + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals( + od.getBoxY(), + Math.round((float) firstHidden * od.getSequencesHeight() + / alheight) + - boxHeight); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /* + * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same. + */ + private void moveViewportH(int startRes) + { - vpranges.setStartRes(startRes); - vpranges.setEndRes(startRes + viewWidth - 1); ++ vpranges.setViewportStartAndWidth(startRes, viewWidth); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + } + + /* + * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same. + */ + private void moveViewportV(int startSeq) + { - vpranges.setStartSeq(startSeq); - vpranges.setEndSeq(startSeq + viewHeight - 1); ++ vpranges.setViewportStartAndHeight(startSeq, viewHeight); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + } + + /* + * Move viewport horizontally and vertically. + */ + private void moveViewport(int startRes, int startSeq) + { - vpranges.setStartRes(startRes); - vpranges.setEndRes(startRes + viewWidth - 1); - vpranges.setStartSeq(startSeq); - vpranges.setEndSeq(startSeq + viewHeight - 1); ++ vpranges.setViewportStartAndWidth(startRes, viewWidth); ++ vpranges.setViewportStartAndHeight(startSeq, viewHeight); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + } + + /* + * Mouse click as position x,y in overview window + */ - private void mouseClick(OverviewDimensionsHideHidden od, int x, int y) ++ private void mouseClick(OverviewDimensions od, int x, int y) + { + od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols); + + // updates require an OverviewPanel to exist which it doesn't here + // so call setBoxPosition() as it would be called by the AlignmentPanel + // normally - - vpranges.setStartRes(od.getScrollCol()); - vpranges.setEndRes(od.getScrollCol() + viewWidth - 1); - vpranges.setStartSeq(od.getScrollRow()); - vpranges.setEndSeq(od.getScrollRow() + viewHeight - 1); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + } + + /* + * Test that the box is positioned with the top left corner at xpos, ypos + * and with the original width and height + */ + private void testBoxIsAtClickPoint(int xpos, int ypos) + { + mouseClick(od, xpos, ypos); + assertEquals(od.getBoxX(), xpos); + assertEquals(od.getBoxY(), ypos); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + } + + /* + * Hide sequences between start and end + */ + private void hideSequences(int start, int end) + { + SequenceI[] allseqs = al.getSequencesArray(); + SequenceGroup theseSeqs = new SequenceGroup(); + + for (int i = start; i <= end; i++) + { + theseSeqs.addSequence(allseqs[i], false); + al.getHiddenSequences().hideSequence(allseqs[i]); + } + + hiddenRepSequences.put(allseqs[start], theseSeqs); + } + } diff --cc test/jalview/viewmodel/OverviewDimensionsShowHiddenTest.java index 0000000,8297159..1bc3bfa mode 000000,100644..100644 --- a/test/jalview/viewmodel/OverviewDimensionsShowHiddenTest.java +++ b/test/jalview/viewmodel/OverviewDimensionsShowHiddenTest.java @@@ -1,0 -1,1029 +1,1025 @@@ + /* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ + package jalview.viewmodel; + + import static org.testng.Assert.assertEquals; + + import jalview.analysis.AlignmentGenerator; + import jalview.datamodel.Alignment; + import jalview.datamodel.AlignmentI; + import jalview.datamodel.ColumnSelection; + import jalview.datamodel.HiddenColumns; + import jalview.datamodel.Sequence; + import jalview.datamodel.SequenceCollectionI; + import jalview.datamodel.SequenceGroup; + import jalview.datamodel.SequenceI; + + import java.util.Hashtable; + + import org.testng.annotations.AfterClass; + import org.testng.annotations.BeforeClass; + import org.testng.annotations.BeforeMethod; + import org.testng.annotations.Test; + + @Test(singleThreaded = true) + public class OverviewDimensionsShowHiddenTest + { + AlignmentI al; + OverviewDimensionsShowHidden od; + + // cached widths and heights + int boxWidth; + int boxHeight; + int viewHeight; + int viewWidth; + int alheight; + int alwidth; + + ViewportRanges vpranges; + + Hashtable hiddenRepSequences = new Hashtable(); + + HiddenColumns hiddenCols = new HiddenColumns(); + + @BeforeClass(alwaysRun = true) + public void setUpAlignment() + { + // create random alignment + AlignmentGenerator gen = new AlignmentGenerator(false); + al = gen.generate(157, 525, 123, 5, 5); + } + + @BeforeMethod(alwaysRun = true) + public void setUp() + { + if (!hiddenRepSequences.isEmpty()) + { + al.getHiddenSequences().showAll(hiddenRepSequences); + } + ColumnSelection colsel = new ColumnSelection(); + hiddenCols.revealAllHiddenColumns(colsel); + + vpranges = new ViewportRanges(al); - vpranges.setStartRes(0); - vpranges.setEndRes(62); - vpranges.setStartSeq(0); - vpranges.setEndSeq(17); ++ vpranges.setViewportStartAndHeight(0, 18); ++ vpranges.setViewportStartAndWidth(0, 63); + + viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1; + viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1; + + HiddenColumns hiddenCols = new HiddenColumns(); + + od = new OverviewDimensionsShowHidden(vpranges, true); + // Initial box sizing - default path through code + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + + mouseClick(od, 0, 0); + moveViewport(0, 0); + + // calculate before hidden columns so we get absolute values + alheight = vpranges.getAbsoluteAlignmentHeight(); + alwidth = vpranges.getAbsoluteAlignmentWidth(); + + boxWidth = Math.round((float) (vpranges.getEndRes() + - vpranges.getStartRes() + 1) + * od.getWidth() / alwidth); + boxHeight = Math.round((float) (vpranges.getEndSeq() + - vpranges.getStartSeq() + 1) + * od.getSequencesHeight() / alheight); + } + + @AfterClass(alwaysRun = true) + public void cleanUp() + { + al = null; + } + + /** + * Test that the OverviewDimensions constructor sets width and height + * correctly + */ + @Test(groups = { "Functional" }) + public void testConstructor() + { + SequenceI seqa = new Sequence("Seq1", "ABC"); + SequenceI seqb = new Sequence("Seq2", "ABC"); + SequenceI seqc = new Sequence("Seq3", "ABC"); + SequenceI seqd = new Sequence("Seq4", "ABC"); + SequenceI seqe = new Sequence("Seq5", + "ABCABCABCABCABCABCABCABCBACBACBACBAC"); + + int defaultGraphHeight = 20; + int maxWidth = 400; + int minWidth = 120; + int maxSeqHeight = 300; + int minSeqHeight = 40; + + // test for alignment with width > height + SequenceI[] seqs1 = new SequenceI[] { seqa, seqb }; + Alignment al1 = new Alignment(seqs1); + ViewportRanges props = new ViewportRanges(al1); + + OverviewDimensions od = new OverviewDimensionsShowHidden(props, true); + int scaledHeight = 267; + assertEquals(od.getGraphHeight(), defaultGraphHeight); + assertEquals(od.getSequencesHeight(), scaledHeight); + assertEquals(od.getWidth(), maxWidth); + assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight); + + // test for alignment with width < height + SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd }; + Alignment al2 = new Alignment(seqs2); + props = new ViewportRanges(al2); + + od = new OverviewDimensionsShowHidden(props, true); + int scaledWidth = 300; + assertEquals(od.getGraphHeight(), defaultGraphHeight); + assertEquals(od.getSequencesHeight(), maxSeqHeight); + assertEquals(od.getWidth(), scaledWidth); + assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight); + + // test for alignment with width > height and sequence height scaled below + // min value + SequenceI[] seqs3 = new SequenceI[] { seqe }; + Alignment al3 = new Alignment(seqs3); + props = new ViewportRanges(al3); + + od = new OverviewDimensionsShowHidden(props, true); + assertEquals(od.getGraphHeight(), defaultGraphHeight); + assertEquals(od.getSequencesHeight(), minSeqHeight); + assertEquals(od.getWidth(), maxWidth); + assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight); + + // test for alignment with width < height and width scaled below min value + SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa, + seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd }; + Alignment al4 = new Alignment(seqs4); + props = new ViewportRanges(al4); + + od = new OverviewDimensionsShowHidden(props, true); + assertEquals(od.getGraphHeight(), defaultGraphHeight); + assertEquals(od.getSequencesHeight(), maxSeqHeight); + assertEquals(od.getWidth(), minWidth); + assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight); + + Alignment al5 = new Alignment(seqs4); + props = new ViewportRanges(al5); + + od = new OverviewDimensionsShowHidden(props, false); + assertEquals(od.getGraphHeight(), 0); + assertEquals(od.getSequencesHeight(), maxSeqHeight); + assertEquals(od.getWidth(), minWidth); + assertEquals(od.getHeight(), maxSeqHeight); + } + + /** + * Test that validation after mouse adjustments to boxX and boxY sets box + * dimensions and scroll values correctly, when there are no hidden rows or + * columns. + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromMouseClick() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // negative boxX value reset to 0 + mouseClick(od, -5, 10); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollRow(), ++ assertEquals(vpranges.getStartSeq(), + Math.round((float) 10 * alheight / od.getSequencesHeight())); - assertEquals(od.getScrollCol(), 0); ++ assertEquals(vpranges.getStartRes(), 0); + + // negative boxY value reset to 0 + mouseClick(od, 6, -2); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) 6 * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // overly large boxX value reset to width-boxWidth + mouseClick(od, 100, 6); + assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth()); + assertEquals(od.getBoxY(), 6); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight())); + + // overly large boxY value reset to sequenceHeight - boxHeight + mouseClick(od, 10, 520); + assertEquals(od.getBoxX(), 10); + assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight()); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); + + // here (float) od.getBoxY() * alheight / od.getSequencesHeight() = 507.5 + // and round rounds to 508; however we get 507 working with row values + // hence the subtraction of 1 - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight()) - 1); + + // click past end of alignment, as above + mouseClick(od, 3000, 5); + assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth()); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight())); + + // move viewport so startRes non-zero and then mouseclick + moveViewportH(50); + + // click at viewport position + int oldboxx = od.getBoxX(); + int oldboxy = od.getBoxY(); + mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2); + assertEquals(od.getBoxX(), oldboxx + 5); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); + assertEquals(od.getBoxY(), oldboxy + 2); - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight())); + + // click at top corner + mouseClick(od, 0, 0); + assertEquals(od.getBoxX(), 0); - assertEquals(od.getScrollCol(), 0); ++ assertEquals(vpranges.getStartRes(), 0); + assertEquals(od.getBoxY(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test setting of the box position, when there are hidden cols at the start + * of the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenColsAtStart() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide cols at start and check updated box position is correct + // changes boxX but not boxwidth + int lastHiddenCol = 30; + hiddenCols.hideColumns(0, lastHiddenCol); + + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), + Math.round((float) (lastHiddenCol + 1) * od.getWidth() + / alwidth)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // try to click in hidden cols, check box does not move + int xpos = 10; + mouseClick(od, xpos, 0); + assertEquals( + od.getBoxX(), + Math.round((float) (lastHiddenCol + 1) * od.getWidth() + / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollRow(), 0); - assertEquals(od.getScrollCol(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); ++ assertEquals(vpranges.getStartRes(), 0); + + // click to right of hidden columns, box moves to click point + testBoxIsAtClickPoint(40, 0); - assertEquals(od.getScrollRow(), 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartSeq(), 0); ++ assertEquals(vpranges.getStartRes(), + Math.round((float) 40 * alwidth / od.getWidth()) + - (lastHiddenCol + 1)); + + // click to right of hidden columns such that box runs over right hand side + // of alignment + // box position is adjusted away from the edge + // overly large boxX value reset to width-boxWidth + xpos = 100; + mouseClick(od, xpos, 5); + assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth()); + assertEquals(od.getBoxY(), 5); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth()) + - (lastHiddenCol + 1)); - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight())); + } + + /** + * Test setting of the box position, when there are hidden cols in the middle + * of the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenColsInMiddle() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide columns 63-73, no change to box position or dimensions + int firstHidden = 63; + int lastHidden = 73; + hiddenCols.hideColumns(firstHidden, lastHidden); + + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // move box so that it overlaps with hidden cols on one side + // box width changes, boxX and scrollCol as for unhidden case + int xpos = 55 - boxWidth; // 55 is position in overview approx halfway + // between cols 60 and 70 + mouseClick(od, xpos, 0); + assertEquals(od.getBoxX(), xpos); + assertEquals(od.getBoxY(), 0); + assertEquals( + od.getBoxWidth(), + Math.round(boxWidth + (float) (lastHidden - firstHidden + 1) + * od.getWidth() / alwidth)); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round(xpos * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // move box so that it completely covers hidden cols + // box width changes, boxX and scrollCol as for hidden case + xpos = 33; + mouseClick(od, xpos, 0); + assertEquals(od.getBoxX(), xpos); + assertEquals(od.getBoxY(), 0); + assertEquals( + od.getBoxWidth(), + Math.round(boxWidth + (float) (lastHidden - firstHidden + 1) + * od.getWidth() / alwidth)); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) xpos * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // move box so boxX is in hidden cols, box overhangs at right + // boxX and scrollCol at left of hidden area, box width extends across + // hidden region + xpos = 50; + mouseClick(od, xpos, 0); + assertEquals(od.getBoxX(), + Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals( + od.getBoxWidth(), + boxWidth + + Math.round((float) (lastHidden - firstHidden + 1) + * od.getWidth() / alwidth)); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), firstHidden - 1); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), firstHidden - 1); ++ assertEquals(vpranges.getStartSeq(), 0); + + // move box so boxX is to right of hidden cols, but does not go beyond full + // width of alignment + // box width, boxX and scrollCol all as for non-hidden case + xpos = 75; + testBoxIsAtClickPoint(xpos, 0); - assertEquals(od.getScrollRow(), 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartSeq(), 0); ++ assertEquals(vpranges.getStartRes(), + Math.round(xpos * alwidth / od.getWidth()) + - (lastHidden - firstHidden + 1)); + + // move box so it goes beyond full width of alignment + // boxX, scrollCol adjusted back, box width normal + xpos = 3000; + mouseClick(od, xpos, 5); + assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth()); + assertEquals(od.getBoxY(), 5); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals( ++ vpranges.getStartRes(), + Math.round(((float) od.getBoxX() * alwidth / od.getWidth()) + - (lastHidden - firstHidden + 1))); - assertEquals(od.getScrollRow(), ++ assertEquals( ++ vpranges.getStartSeq(), + Math.round((float) od.getBoxY() * alheight + / od.getSequencesHeight())); + + } + + /** + * Test setting of the box position, when there are hidden cols at the end of + * the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenColsAtEnd() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide columns 140-164, no change to box position or dimensions + int firstHidden = 140; + int lastHidden = 164; + hiddenCols.hideColumns(firstHidden, lastHidden); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // click to left of hidden cols, without overlapping + // boxX, scrollCol and width as normal + int xpos = 5; + testBoxIsAtClickPoint(xpos, 0); - assertEquals(od.getScrollRow(), 0); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartSeq(), 0); ++ assertEquals(vpranges.getStartRes(), + Math.round((float) xpos * alwidth / od.getWidth())); + + // click to left of hidden cols, with overlap + // boxX and scrollCol adjusted for hidden cols, width normal + xpos = Math.round((float) 145 * od.getWidth() / alwidth) - boxWidth; + mouseClick(od, xpos, 0); + assertEquals(od.getBoxX(), + Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth) + - boxWidth + 1); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // click in hidden cols + // boxX and scrollCol adjusted for hidden cols, width normal + xpos = 115; + assertEquals(od.getBoxX(), + Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth) + - boxWidth + 1); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // click off end of alignment + // boxX and scrollCol adjusted for hidden cols, width normal + xpos = 3000; + assertEquals(od.getBoxX(), + Math.round((float) (firstHidden - 1) * od.getWidth() / alwidth) + - boxWidth + 1); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), ++ assertEquals(vpranges.getStartRes(), + Math.round((float) od.getBoxX() * alwidth / od.getWidth())); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + } + + /** + * Test that the box position is set correctly when set from the viewport, + * with no hidden rows or columns + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewport() + { + // move viewport to start of alignment + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to right + moveViewportH(70); + assertEquals(od.getBoxX(), + Math.round((float) 70 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport down + moveViewportV(100); + assertEquals(od.getBoxX(), + Math.round((float) 70 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), + Math.round(100 * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to bottom right + moveViewport(98, 508); + assertEquals(od.getBoxX(), + Math.round((float) 98 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), + Math.round((float) 508 * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden columns + * at the start + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenColsAtStart() + { + int firstHidden = 0; + int lastHidden = 20; + hiddenCols.hideColumns(firstHidden, lastHidden); + + // move viewport to start of alignment + moveViewport(0, 0); + assertEquals(od.getBoxX(), + Math.round((float) (lastHidden + 1) * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to end of alignment - need to make startRes by removing + // hidden cols because of how viewport/overview are implemented + moveViewport(98 - lastHidden - 1, 0); + assertEquals(od.getBoxX(), + Math.round((float) 98 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden columns + * in the middle + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenColsInMiddle() + { + int firstHidden = 68; + int lastHidden = 78; + hiddenCols.hideColumns(firstHidden, lastHidden); + + // move viewport before hidden columns + moveViewport(3, 0); + + assertEquals(od.getBoxX(), + Math.round((float) 3 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to left of hidden columns with overlap + moveViewport(10, 0); + assertEquals(od.getBoxX(), + Math.round((float) 10 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals( + od.getBoxWidth(), + boxWidth + + Math.round((float) (lastHidden - firstHidden + 1) + * od.getWidth() / alwidth)); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to straddle hidden columns + moveViewport(63, 0); + assertEquals(od.getBoxX(), + Math.round((float) 63 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals( + od.getBoxWidth(), + boxWidth + + Math.round((lastHidden - firstHidden + 1) + * od.getWidth() / alwidth)); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to right of hidden columns, no overlap + moveViewport(80 - (lastHidden - firstHidden + 1), 0); + assertEquals(od.getBoxX(), + Math.round((float) 80 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + } + + /** + * Test that the box position is set correctly when there are hidden columns + * at the end + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenColsAtEnd() + { + int firstHidden = 152; + int lastHidden = 164; + hiddenCols.hideColumns(firstHidden, lastHidden); + + // move viewport before hidden columns + moveViewport(3, 0); + assertEquals(od.getBoxX(), + Math.round((float) 3 * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to hidden columns + // viewport can't actually extend into hidden cols, + // so move to the far right edge of the viewport + moveViewport(firstHidden - viewWidth, 0); + assertEquals(od.getBoxX(), + Math.round((float) (firstHidden - viewWidth) + * od.getWidth() / alwidth)); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden rows at + * the start + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenRowsAtStart() + { + int firstHidden = 0; + int lastHidden = 20; + hideSequences(firstHidden, lastHidden); + + // move viewport to start of alignment: + // box moves to below hidden rows, height remains same + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), + Math.round((float) (lastHidden + 1) * od.getSequencesHeight() + / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to end of alignment + moveViewport(0, 525 - viewHeight - lastHidden - 1); + assertEquals(od.getBoxX(), 0); + assertEquals( + od.getBoxY(), + Math.round((float) (525 - viewHeight) * od.getSequencesHeight() + / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test that the box position is set correctly when there are hidden rows in + * the middle + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenRowsInMiddle() + { + int firstHidden = 200; + int lastHidden = 210; + hideSequences(firstHidden, lastHidden); + + // move viewport to start of alignment: + // box, height etc as in non-hidden case + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to straddle hidden rows + moveViewport(0, 198); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), Math.round ((float)198 * od.getSequencesHeight() + / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals( + od.getBoxHeight(), + Math.round((float) (viewHeight + lastHidden - firstHidden + 1) + * od.getSequencesHeight() / alheight)); + } + + /** + * Test that the box position is set correctly when there are hidden rows at + * the bottom + */ + @Test(groups = { "Functional" }) + public void testSetBoxFromViewportHiddenRowsAtEnd() + { + int firstHidden = 500; + int lastHidden = 524; + hideSequences(firstHidden, lastHidden); + + // move viewport to start of alignment: + // box, height etc as in non-hidden case + moveViewport(0, 0); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // move viewport to end of alignment + // viewport sits above hidden rows and does not include them + moveViewport(0, firstHidden - viewHeight - 1); + assertEquals(od.getBoxX(), 0); + assertEquals( + od.getBoxY(), + Math.round((float) (firstHidden - viewHeight - 1) + * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + } + + /** + * Test setting of the box position, when there are hidden rows at the start + * of the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenRowsAtStart() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxHeight(), boxHeight); + assertEquals(od.getBoxWidth(), boxWidth); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ 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); + assertEquals( + od.getBoxY(), + Math.round((float) (lastHiddenRow + 1) + * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click below hidden rows + mouseClick(od, 0, 150); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 150); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /** + * Test setting of the box position, when there are hidden rows at the middle + * of the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenRowsInMiddle() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide rows in middle and check updated box position is correct + // no changes + int firstHiddenRow = 50; + int lastHiddenRow = 54; + hideSequences(firstHiddenRow, lastHiddenRow); + + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click above hidden rows, so that box overlaps + int ypos = 35; // column value in residues + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals( + od.getBoxHeight(), + boxHeight + + Math.round((float) (lastHiddenRow - firstHiddenRow + 1) + * od.getSequencesHeight() / alheight)); + + // click so that box straddles hidden rows + ypos = 44; // column value in residues + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals( + od.getBoxHeight(), + boxHeight + + Math.round((float) (lastHiddenRow - firstHiddenRow + 1) + * od.getSequencesHeight() / alheight)); + } + + /** + * Test setting of the box position, when there are hidden rows at the end of + * the alignment + */ + @Test(groups = { "Functional" }) + public void testFromMouseWithHiddenRowsAtEnd() + { + od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); - assertEquals(od.getScrollCol(), 0); - assertEquals(od.getScrollRow(), 0); ++ assertEquals(vpranges.getStartRes(), 0); ++ assertEquals(vpranges.getStartSeq(), 0); + + // hide rows at end and check updated box position is correct + // no changes + int firstHidden = 500; + int lastHidden = 524; + hideSequences(firstHidden, lastHidden); + + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), 0); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click above hidden rows + int ypos = 40; // row 40 + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals(od.getBoxY(), + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click above hidden rows so box overlaps + // boxY moved upwards, boxHeight remains same + ypos = 497; // row 497 + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals( + od.getBoxY(), + Math.round((float) (firstHidden - viewHeight) + * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + // click within hidden rows + ypos = 505; + mouseClick(od, 0, + Math.round((float) ypos * od.getSequencesHeight() / alheight)); + assertEquals(od.getBoxX(), 0); + assertEquals( + od.getBoxY(), + Math.round((firstHidden - viewHeight) * od.getSequencesHeight() + / alheight)); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + } + + /* + * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same. + */ + private void moveViewportH(int startRes) + { - vpranges.setStartRes(startRes); - vpranges.setEndRes(startRes + viewWidth - 1); ++ vpranges.setViewportStartAndWidth(startRes, viewWidth); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + } + + /* + * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same. + */ + private void moveViewportV(int startSeq) + { - vpranges.setStartSeq(startSeq); - vpranges.setEndSeq(startSeq + viewHeight - 1); ++ vpranges.setViewportStartAndHeight(startSeq, viewHeight); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + } + + /* + * Move viewport horizontally and vertically. + */ + private void moveViewport(int startRes, int startSeq) + { - vpranges.setStartRes(startRes); - vpranges.setEndRes(startRes + viewWidth - 1); - vpranges.setStartSeq(startSeq); - vpranges.setEndSeq(startSeq + viewHeight - 1); ++ vpranges.setViewportStartAndWidth(startRes, viewWidth); ++ vpranges.setViewportStartAndHeight(startSeq, viewHeight); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + } + + /* + * Mouse click as position x,y in overview window + */ - private void mouseClick(OverviewDimensionsShowHidden od, int x, int y) ++ private void mouseClick(OverviewDimensions od, int x, int y) + { + od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols); + + // updates require an OverviewPanel to exist which it doesn't here + // so call setBoxPosition() as it would be called by the AlignmentPanel + // normally - - vpranges.setStartRes(od.getScrollCol()); - vpranges.setEndRes(od.getScrollCol() + viewWidth - 1); - vpranges.setStartSeq(od.getScrollRow()); - vpranges.setEndSeq(od.getScrollRow() + viewHeight - 1); + od.setBoxPosition(al.getHiddenSequences(), hiddenCols); + } + + /* + * Test that the box is positioned with the top left corner at xpos, ypos + * and with the original width and height + */ + private void testBoxIsAtClickPoint(int xpos, int ypos) + { + mouseClick(od, xpos, ypos); + assertEquals(od.getBoxX(), xpos); + assertEquals(od.getBoxY(), ypos); + assertEquals(od.getBoxWidth(), boxWidth); + assertEquals(od.getBoxHeight(), boxHeight); + + } + + /* + * Hide sequences between start and end + */ + private void hideSequences(int start, int end) + { + SequenceI[] allseqs = al.getSequencesArray(); + SequenceGroup theseSeqs = new SequenceGroup(); + + for (int i = start; i <= end; i++) + { + theseSeqs.addSequence(allseqs[i], false); + al.getHiddenSequences().hideSequence(allseqs[i]); + } + + hiddenRepSequences.put(allseqs[start], theseSeqs); + } + }