From: kiramt Date: Wed, 19 Apr 2017 11:01:30 +0000 (+0100) Subject: Merge remote-tracking branch 'origin/develop' into X-Git-Tag: Release_2_10_2~3^2~92^2~19 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=484abc22be60686d5188c8ff1b90613e821ea946;hp=242fe71de915d94d6f73d790bb14e377bb9624d3;p=jalview.git Merge remote-tracking branch 'origin/develop' into features/JAL-2388OverviewWindow Conflicts: resources/lang/Messages_es.properties --- diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 1184c1f..a7723e9 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -1297,3 +1297,4 @@ warn.name_cannot_be_duplicate = User-defined URL names must be unique and cannot label.invalid_name = Invalid Name ! label.output_seq_details = Output Sequence Details to list all database references label.urllinks = Links +label.togglehidden = Toggle hidden columns on/off \ No newline at end of file diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index a878ab7..4c665ff 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -1287,3 +1287,4 @@ warn.name_cannot_be_duplicate = Los nombres URL definidos por el usuario deben s label.invalid_name = Nombre inválido ! label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas label.urllinks = Enlaces +label.togglehidden = Toggle hidden columns on/off \ No newline at end of file diff --git a/src/jalview/appletgui/AlignViewport.java b/src/jalview/appletgui/AlignViewport.java index 065c503..b289be7 100644 --- a/src/jalview/appletgui/AlignViewport.java +++ b/src/jalview/appletgui/AlignViewport.java @@ -39,7 +39,6 @@ import jalview.structure.SelectionSource; import jalview.structure.StructureSelectionManager; import jalview.structure.VamsasSource; import jalview.viewmodel.AlignmentViewport; -import jalview.viewmodel.ViewportRanges; import java.awt.Font; @@ -71,11 +70,10 @@ public class AlignViewport extends AlignmentViewport implements public AlignViewport(AlignmentI al, JalviewLite applet) { - super(); + super(al); calculator = new jalview.workers.AlignCalcManager(); this.applet = applet; - alignment = al; - ranges = new ViewportRanges(this.alignment); + // we always pad gaps this.setPadGaps(true); diff --git a/src/jalview/appletgui/OverviewCanvas.java b/src/jalview/appletgui/OverviewCanvas.java new file mode 100644 index 0000000..51819cd --- /dev/null +++ b/src/jalview/appletgui/OverviewCanvas.java @@ -0,0 +1,254 @@ +/* + * 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.appletgui; + +import jalview.datamodel.SequenceI; +import jalview.renderer.seqfeatures.FeatureColourFinder; +import jalview.viewmodel.OverviewDimensions; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; + +import javax.swing.JComponent; + +public class OverviewCanvas extends JComponent +{ + // This is set true if the alignment view changes whilst + // the overview is being calculated + private volatile boolean restart = false; + + private volatile boolean updaterunning = false; + + private OverviewDimensions od; + + private Image miniMe; + + private Image offscreen; + + private AlignViewport av; + + // Can set different properties in this seqCanvas than + // main visible SeqCanvas + private SequenceRenderer sr; + + private FeatureRenderer fr; + + private Frame nullFrame; + + public OverviewCanvas(OverviewDimensions overviewDims, + AlignViewport alignvp) + { + od = overviewDims; + av = alignvp; + + nullFrame = new Frame(); + nullFrame.addNotify(); + + sr = new SequenceRenderer(av); + sr.graphics = nullFrame.getGraphics(); + sr.renderGaps = false; + sr.forOverview = true; + fr = new FeatureRenderer(av); + } + + /* + * Signals to drawing code that the associated alignment viewport + * has changed and a redraw will be required + */ + public boolean restartDraw() + { + synchronized (this) + { + if (updaterunning) + { + restart = true; + } + else + { + updaterunning = true; + } + return restart; + } + } + + public void draw(boolean showSequenceFeatures, boolean showAnnotation, + AlignmentPanel ap) + { + miniMe = null; + + if (av.isShowSequenceFeatures()) + { + fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer()); + } + + setPreferredSize(new Dimension(od.getWidth(), od.getHeight())); + + miniMe = nullFrame.createImage(od.getWidth(), od.getHeight()); + offscreen = nullFrame.createImage(od.getWidth(), od.getHeight()); + + Graphics mg = miniMe.getGraphics(); + + int alwidth = av.getAlignment().getWidth(); + int alheight = av.getAlignment().getAbsoluteHeight(); + float sampleCol = alwidth / (float) od.getWidth(); + float sampleRow = alheight / (float) od.getSequencesHeight(); + + buildImage(sampleRow, sampleCol, mg); + + // check for conservation annotation to make sure overview works for DNA too + if (showAnnotation) + { + for (int col = 0; col < od.getWidth() && !restart; col++) + { + mg.translate(col, od.getSequencesHeight()); + ap.annotationPanel.renderer.drawGraph(mg, + av.getAlignmentConservationAnnotation(), + av.getAlignmentConservationAnnotation().annotations, + (int) (sampleCol) + 1, od.getGraphHeight(), + (int) (col * sampleCol), (int) (col * sampleCol) + 1); + mg.translate(-col, -od.getSequencesHeight()); + } + } + System.gc(); + + if (restart) + { + restart = false; + draw(showSequenceFeatures, showAnnotation, ap); + } + else + { + updaterunning = false; + } + } + + /* + * Build the overview panel image + */ + private void buildImage(float sampleRow, float sampleCol, Graphics mg) + { + int lastcol = 0; + int lastrow = 0; + int xstart = 0; + int ystart = 0; + Color color = Color.yellow; + int sameRow = 0; + int sameCol = 0; + + SequenceI seq = null; + FeatureColourFinder finder = new FeatureColourFinder(fr); + + final boolean hasHiddenCols = av.hasHiddenColumns(); + boolean hiddenRow = false; + + for (int row = 0; row < od.getSequencesHeight() && !restart; row++) + { + if ((int) (row * sampleRow) == lastrow) + { + sameRow++; + } + else + { + // 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(); col++) + { + if ((int) (col * sampleCol) == lastcol + && (int) (row * sampleRow) == lastrow) + { + sameCol++; + } + else + { + lastcol = (int) (col * sampleCol); + + color = getColumnColourFromSequence(seq, hiddenRow, + hasHiddenCols, lastcol, finder); + + mg.setColor(color); + if (sameCol == 1 && sameRow == 1) + { + mg.drawLine(xstart, ystart, xstart, ystart); + } + else + { + mg.fillRect(xstart, ystart, sameCol, sameRow); + } + + xstart = col; + sameCol = 1; + } + } + lastrow = (int) (row * sampleRow); + ystart = row; + sameRow = 1; + } + } + } + + /* + * Find the colour of a sequence at a specified column position + */ + private Color getColumnColourFromSequence( + jalview.datamodel.SequenceI seq, boolean hiddenRow, + boolean hasHiddenCols, int lastcol, FeatureColourFinder finder) + { + Color color = Color.white; + if (seq.getLength() > lastcol) + { + color = sr.getResidueColour(seq, lastcol, finder); + } + + if (hiddenRow + || (hasHiddenCols && !av.getColumnSelection() + .isVisible(lastcol))) + { + color = color.darker().darker(); + } + return color; + } + + @Override + public void update(Graphics g) + { + paint(g); + } + + @Override + public void paint(Graphics g) + { + Graphics og = offscreen.getGraphics(); + if (miniMe != null) + { + og.drawImage(miniMe, 0, 0, this); + og.setColor(Color.red); + od.drawBox(og); + g.drawImage(offscreen, 0, 0, this); + } + } + +} diff --git a/src/jalview/appletgui/OverviewPanel.java b/src/jalview/appletgui/OverviewPanel.java index 3ef2936..de192fa 100755 --- a/src/jalview/appletgui/OverviewPanel.java +++ b/src/jalview/appletgui/OverviewPanel.java @@ -20,15 +20,10 @@ */ package jalview.appletgui; -import jalview.datamodel.SequenceI; -import jalview.renderer.seqfeatures.FeatureColourFinder; -import jalview.viewmodel.OverviewDimensions; +import jalview.viewmodel.OverviewDimensionsWithHidden; -import java.awt.Color; +import java.awt.BorderLayout; import java.awt.Dimension; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.Image; import java.awt.Panel; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; @@ -39,47 +34,29 @@ import java.awt.event.MouseMotionListener; public class OverviewPanel extends Panel implements Runnable, MouseMotionListener, MouseListener { - private OverviewDimensions od; + private OverviewDimensionsWithHidden od; - private Image miniMe; - - private Image offscreen; + private OverviewCanvas oviewCanvas; private AlignViewport av; private AlignmentPanel ap; - private boolean resizing = false; - - // This is set true if the user resizes whilst - // the overview is being calculated - private boolean resizeAgain = false; - - // Can set different properties in this seqCanvas than - // main visible SeqCanvas - private SequenceRenderer sr; - - private FeatureRenderer fr; - - private Frame nullFrame; + private boolean updateRunning = false; public OverviewPanel(AlignmentPanel alPanel) { 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 OverviewDimensionsWithHidden(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())); addComponentListener(new ComponentAdapter() { @@ -155,19 +132,6 @@ public class OverviewPanel extends Panel implements Runnable, */ public void updateOverviewImage() { - if (resizing) - { - resizeAgain = true; - return; - } - - if (av.isShowSequenceFeatures()) - { - fr.transferSettings(ap.seqPanel.seqCanvas.fr); - } - - resizing = true; - if ((getSize().width > 0) && (getSize().height > 0)) { od.setWidth(getSize().width); @@ -175,156 +139,26 @@ public class OverviewPanel extends Panel implements Runnable, } setSize(new Dimension(od.getWidth(), od.getHeight())); + if (updateRunning) + { + oviewCanvas.restartDraw(); + return; + } + + updateRunning = true; Thread thread = new Thread(this); thread.start(); repaint(); + updateRunning = false; } @Override public void run() { - miniMe = null; - - if (av.isShowSequenceFeatures()) - { - fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer()); - } - - if (getSize().width > 0 && getSize().height > 0) - { - od.setWidth(getSize().width); - od.setHeight(getSize().height); - } - - setSize(new Dimension(od.getWidth(), od.getHeight())); - - miniMe = nullFrame.createImage(od.getWidth(), od.getHeight()); - offscreen = nullFrame.createImage(od.getWidth(), od.getHeight()); - - Graphics mg = miniMe.getGraphics(); - - int alwidth = av.getAlignment().getWidth(); - int alheight = av.getAlignment().getAbsoluteHeight(); - float sampleCol = alwidth / (float) od.getWidth(); - float sampleRow = alheight / (float) od.getSequencesHeight(); - - buildImage(sampleRow, sampleCol, mg); - - // check for conservation annotation to make sure overview works for DNA too - if (av.isShowAnnotation() - && (av.getAlignmentConservationAnnotation() != null)) - { - for (int col = 0; col < od.getWidth() && !resizeAgain; col++) - { - mg.translate(col, od.getSequencesHeight()); - ap.annotationPanel.renderer.drawGraph(mg, - av.getAlignmentConservationAnnotation(), - av.getAlignmentConservationAnnotation().annotations, - (int) (sampleCol) + 1, od.getGraphHeight(), - (int) (col * sampleCol), (int) (col * sampleCol) + 1); - mg.translate(-col, -od.getSequencesHeight()); - } - } - System.gc(); - - resizing = false; - + oviewCanvas.draw(av.isShowSequenceFeatures(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null), ap); setBoxPosition(); - - if (resizeAgain) - { - resizeAgain = false; - updateOverviewImage(); - } - } - - /* - * Build the overview panel image - */ - private void buildImage(float sampleRow, float sampleCol, Graphics mg) - { - int lastcol = 0; - int lastrow = 0; - int xstart = 0; - int ystart = 0; - Color color = Color.yellow; - int sameRow = 0; - int sameCol = 0; - - SequenceI seq = null; - FeatureColourFinder finder = new FeatureColourFinder(fr); - - final boolean hasHiddenCols = av.hasHiddenColumns(); - boolean hiddenRow = false; - - for (int row = 0; row <= od.getSequencesHeight() && !resizeAgain; row++) - { - if ((int) (row * sampleRow) == lastrow) - { - sameRow++; - } - else - { - // get the sequence which would be at alignment index 'lastrow' if no - // columns 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(); col++) - { - if ((int) (col * sampleCol) == lastcol - && (int) (row * sampleRow) == lastrow) - { - sameCol++; - } - else - { - lastcol = (int) (col * sampleCol); - - color = getColumnColourFromSequence(seq, hiddenRow, - hasHiddenCols, lastcol, finder); - - mg.setColor(color); - if (sameCol == 1 && sameRow == 1) - { - mg.drawLine(xstart, ystart, xstart, ystart); - } - else - { - mg.fillRect(xstart, ystart, sameCol, sameRow); - } - - xstart = col; - sameCol = 1; - } - } - lastrow = (int) (row * sampleRow); - ystart = row; - sameRow = 1; - } - } - } - - /* - * Find the colour of a sequence at a specified column position - */ - private Color getColumnColourFromSequence( - jalview.datamodel.SequenceI seq, boolean hiddenRow, - boolean hasHiddenCols, int lastcol, FeatureColourFinder finder) - { - Color color = Color.white; - if (seq.getLength() > lastcol) - { - color = sr.getResidueColour(seq, lastcol, finder); - } - - if (hiddenRow - || (hasHiddenCols && !av.getColumnSelection() - .isVisible(lastcol))) - { - color = color.darker().darker(); - } - return color; } /** @@ -338,24 +172,4 @@ public class OverviewPanel extends Panel implements Runnable, .getHiddenSequences(), av.getColumnSelection(), av.getRanges()); repaint(); } - - @Override - public void update(Graphics g) - { - paint(g); - } - - @Override - public void paint(Graphics g) - { - Graphics og = offscreen.getGraphics(); - if (miniMe != null) - { - og.drawImage(miniMe, 0, 0, this); - og.setColor(Color.red); - od.drawBox(og); - g.drawImage(offscreen, 0, 0, this); - } - } - } diff --git a/src/jalview/datamodel/AlignmentColsCollection.java b/src/jalview/datamodel/AlignmentColsCollection.java new file mode 100644 index 0000000..3a9f598 --- /dev/null +++ b/src/jalview/datamodel/AlignmentColsCollection.java @@ -0,0 +1,51 @@ +/* + * 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.datamodel; + +import java.util.Iterator; + +public class AlignmentColsCollection implements Iterable +{ + int start; + int end; + ColumnSelection hidden; + + public AlignmentColsCollection(int s, int e, ColumnSelection colsel) + { + start = s; + end = e; + hidden = colsel; + } + + @Override + public Iterator iterator() + { + return new AllColsIterator(start,end,hidden); + } + + /** + * Answers if the column at the the current position is hidden. + */ + public boolean isHidden(int c) + { + return !hidden.isVisible(c); + } +} diff --git a/src/jalview/datamodel/AlignmentRowsCollection.java b/src/jalview/datamodel/AlignmentRowsCollection.java new file mode 100644 index 0000000..e22d8fc --- /dev/null +++ b/src/jalview/datamodel/AlignmentRowsCollection.java @@ -0,0 +1,62 @@ +/* + * 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.datamodel; + +import java.util.Iterator; + +public class AlignmentRowsCollection implements Iterable +{ + int start; + + int end; + + AlignmentI alignment; + + HiddenSequences hidden; + + public AlignmentRowsCollection(int s, int e, AlignmentI al) + { + start = s; + end = e; + alignment = al; + hidden = al.getHiddenSequences(); + } + + @Override + public Iterator iterator() + { + return new AllRowsIterator(start, end, alignment); + } + + /** + * Answers if the sequence at the position is hidden. + */ + public boolean isHidden(int seq) + { + return hidden.isHidden(seq); + } + + public SequenceI getSequence(int seq) + { + return alignment.getSequenceAtAbsoluteIndex(seq); + } +} + diff --git a/src/jalview/datamodel/AllColsIterator.java b/src/jalview/datamodel/AllColsIterator.java new file mode 100644 index 0000000..4e1ff2e --- /dev/null +++ b/src/jalview/datamodel/AllColsIterator.java @@ -0,0 +1,77 @@ +/* + * 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.datamodel; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * An iterator which iterates over all columns or rows in an alignment, whether + * hidden or visible. + * + * @author kmourao + * + */ +public class AllColsIterator implements Iterator +{ + private int last; + + private int next; + + private int current; + + ColumnSelection hidden; + + public AllColsIterator(int firstcol, int lastcol, + ColumnSelection hiddenCols) + { + last = lastcol; + next = firstcol; + current = firstcol; + hidden = hiddenCols; + } + + @Override + public boolean hasNext() + { + return current + 1 <= last; + } + + @Override + public Integer next() + { + if (current + 1 > last) + { + throw new NoSuchElementException(); + } + current = next; + next++; + + return current; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } +} + diff --git a/src/jalview/datamodel/AllRowsIterator.java b/src/jalview/datamodel/AllRowsIterator.java new file mode 100644 index 0000000..aefed60 --- /dev/null +++ b/src/jalview/datamodel/AllRowsIterator.java @@ -0,0 +1,77 @@ +/* + * 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.datamodel; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * An iterator which iterates over all columns or rows in an alignment, whether + * hidden or visible. + * + * @author kmourao + * + */ +public class AllRowsIterator implements Iterator +{ + private int last; + + private int next; + + private int current; + + private AlignmentI al; + + public AllRowsIterator(int firstrow, int lastrow, AlignmentI alignment) + { + last = lastrow; + current = firstrow; + next = firstrow; + al = alignment; + } + + @Override + public boolean hasNext() + { + return current + 1 <= last; + } + + @Override + public Integer next() + { + if (current + 1 > last) + { + throw new NoSuchElementException(); + } + current = next; + next++; + + return current; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } +} + + diff --git a/src/jalview/datamodel/HiddenSequences.java b/src/jalview/datamodel/HiddenSequences.java index 6950c28..1daaf43 100755 --- a/src/jalview/datamodel/HiddenSequences.java +++ b/src/jalview/datamodel/HiddenSequences.java @@ -403,4 +403,20 @@ public class HiddenSequences return false; } + + /** + * Answers if a sequence is hidden + * + * @param seq + * (absolute) index to test + * @return true if sequence at index seq is hidden + */ + public boolean isHidden(int seq) + { + if (hiddenSequences != null) + { + return (hiddenSequences[seq] != null); + } + return false; + } } diff --git a/src/jalview/datamodel/VisibleColsIterator.java b/src/jalview/datamodel/VisibleColsIterator.java new file mode 100644 index 0000000..2a69a82 --- /dev/null +++ b/src/jalview/datamodel/VisibleColsIterator.java @@ -0,0 +1,131 @@ +/* + * 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.datamodel; + +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * An iterator which iterates over all visible columns in an alignment + * + * @author kmourao + * + */ +public class VisibleColsIterator implements Iterator +{ + private int last; + + private int current; + + private int next; + + private List hidden; + + private int lasthiddenregion; + + public VisibleColsIterator(int firstcol, int lastcol, + ColumnSelection hiddenCols) + { + last = lastcol; + current = firstcol; + next = firstcol; + hidden = hiddenCols.getHiddenColumns(); + lasthiddenregion = -1; + + if (hidden != null) + { + int i = 0; + for (i = 0; i < hidden.size(); ++i) + { + if (current >= hidden.get(i)[0] && current <= hidden.get(i)[1]) + { + // current is hidden, move to right + current = hidden.get(i)[1] + 1; + next = current; + } + if (current < hidden.get(i)[0]) + { + break; + } + } + lasthiddenregion = i - 1; + + for (i = hidden.size() - 1; i >= 0; --i) + { + if (last >= hidden.get(i)[0] && last <= hidden.get(i)[1]) + { + // last is hidden, move to left + last = hidden.get(i)[0] - 1; + } + if (last > hidden.get(i)[1]) + { + break; + } + } + } + } + + @Override + public boolean hasNext() + { + return next <= last; + } + + @Override + public Integer next() + { + if (next > last) + { + throw new NoSuchElementException(); + } + current = next; + if ((hidden != null) && (lasthiddenregion + 1 < hidden.size())) + { + // still some more hidden regions + if (next + 1 < hidden.get(lasthiddenregion + 1)[0]) + { + // next+1 is still before the next hidden region + next++; + } + else if ((next + 1 >= hidden.get(lasthiddenregion + 1)[0]) + && (next + 1 <= hidden.get(lasthiddenregion + 1)[1])) + { + // next + 1 is in the next hidden region + next = hidden.get(lasthiddenregion + 1)[1] + 1; + lasthiddenregion++; + } + } + else + { + // finished with hidden regions, just increment normally + next++; + } + return current; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } +} + diff --git a/src/jalview/datamodel/VisibleRowsIterator.java b/src/jalview/datamodel/VisibleRowsIterator.java new file mode 100644 index 0000000..0259fd3 --- /dev/null +++ b/src/jalview/datamodel/VisibleRowsIterator.java @@ -0,0 +1,99 @@ +/* + * 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.datamodel; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * An iterator which iterates over all visible rows in an alignment + * + * @author kmourao + * + */ +public class VisibleRowsIterator implements Iterator +{ + private int last; + + private int current; + + private int next; + + private HiddenSequences hidden; + + private AlignmentI al; + + /** + * Create an iterator for all visible rows in the alignment + * + * @param firstrow + * absolute row index to start from + * @param lastrow + * absolute row index to end at + * @param alignment + * alignment to work with + */ + public VisibleRowsIterator(int firstrow, int lastrow, AlignmentI alignment) + { + al = alignment; + current = firstrow; + last = lastrow; + hidden = al.getHiddenSequences(); + while (hidden.isHidden(last) && last > current) + { + last--; + } + current = firstrow; + while (hidden.isHidden(current) && current < last) + { + current++; + } + next = current; + } + + @Override + public boolean hasNext() + { + return next <= last; + } + + @Override + public Integer next() + { + if (next > last) + { + throw new NoSuchElementException(); + } + current = next; + do + { + next++; + } while (hidden.isHidden(next) && next <= last); + return current; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } +} + diff --git a/src/jalview/gui/AlignViewport.java b/src/jalview/gui/AlignViewport.java index 602e3a1..ef3593c 100644 --- a/src/jalview/gui/AlignViewport.java +++ b/src/jalview/gui/AlignViewport.java @@ -51,7 +51,6 @@ import jalview.structure.StructureSelectionManager; import jalview.structure.VamsasSource; import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; -import jalview.viewmodel.ViewportRanges; import jalview.ws.params.AutoCalcSetting; import java.awt.Container; @@ -105,7 +104,7 @@ public class AlignViewport extends AlignmentViewport implements */ public AlignViewport(AlignmentI al) { - setAlignment(al); + super(al); init(); } @@ -123,6 +122,7 @@ public class AlignViewport extends AlignmentViewport implements public AlignViewport(AlignmentI al, String seqsetid, String viewid) { + super(al); sequenceSetID = seqsetid; viewId = viewid; // TODO remove these once 2.4.VAMSAS release finished @@ -135,8 +135,8 @@ public class AlignViewport extends AlignmentViewport implements { Cache.log.debug("Setting viewport's view id : " + viewId); } - setAlignment(al); init(); + } /** @@ -149,7 +149,7 @@ public class AlignViewport extends AlignmentViewport implements */ public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns) { - setAlignment(al); + super(al); if (hiddenColumns != null) { colSel = hiddenColumns; @@ -184,6 +184,7 @@ public class AlignViewport extends AlignmentViewport implements public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns, String seqsetid, String viewid) { + super(al); sequenceSetID = seqsetid; viewId = viewid; // TODO remove these once 2.4.VAMSAS release finished @@ -196,7 +197,7 @@ public class AlignViewport extends AlignmentViewport implements { Cache.log.debug("Setting viewport's view id : " + viewId); } - setAlignment(al); + if (hiddenColumns != null) { colSel = hiddenColumns; @@ -238,7 +239,6 @@ public class AlignViewport extends AlignmentViewport implements void init() { - ranges = new ViewportRanges(this.alignment); applyViewProperties(); String fontName = Cache.getDefault("FONT_NAME", "SansSerif"); diff --git a/src/jalview/gui/OverviewCanvas.java b/src/jalview/gui/OverviewCanvas.java new file mode 100644 index 0000000..e4c2056 --- /dev/null +++ b/src/jalview/gui/OverviewCanvas.java @@ -0,0 +1,170 @@ +/* + * 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.gui; + +import jalview.api.AlignViewportI; +import jalview.renderer.seqfeatures.FeatureColourFinder; +import jalview.viewmodel.OverviewDimensions; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.image.BufferedImage; + +import javax.swing.JComponent; + + +public class OverviewCanvas extends JComponent +{ + private static final Color TRANS_GREY = new Color(100, 100, 100, 25); + + // This is set true if the alignment view changes whilst + // the overview is being calculated + private volatile boolean restart = false; + + private volatile boolean updaterunning = false; + + private BufferedImage miniMe; + + private BufferedImage lastMiniMe = null; + + // Can set different properties in this seqCanvas than + // main visible SeqCanvas + private SequenceRenderer sr; + + private jalview.renderer.seqfeatures.FeatureRenderer fr; + + OverviewDimensions od; + + AlignViewportI av; + + public OverviewCanvas(OverviewDimensions overviewDims, + AlignViewportI alignvp) + { + od = overviewDims; + av = alignvp; + + sr = new SequenceRenderer(av); + sr.renderGaps = false; + sr.forOverview = true; + fr = new jalview.renderer.seqfeatures.FeatureRenderer(av); + } + + public void resetOviewDims(OverviewDimensions overviewDims) + { + od = overviewDims; + } + + /* + * Signals to drawing code that the associated alignment viewport + * has changed and a redraw will be required + */ + public boolean restartDraw() + { + synchronized (this) + { + if (updaterunning) + { + restart = true; + } + else + { + updaterunning = true; + } + return restart; + } + } + + public void draw(boolean showSequenceFeatures, boolean showAnnotation, + FeatureRenderer transferRenderer) + { + miniMe = null; + + if (showSequenceFeatures) + { + fr.transferSettings(transferRenderer); + } + FeatureColourFinder finder = new FeatureColourFinder(fr); + + // why do we need to set preferred size again? was set in + // updateOverviewImage + setPreferredSize(new Dimension(od.getWidth(), od.getHeight())); + + OverviewRenderer or = new OverviewRenderer(sr, finder, od); + miniMe = or.draw(od.getRows(av.getRanges(), av.getAlignment()), + od.getColumns(av.getRanges(), av.getColumnSelection())); + + Graphics mg = miniMe.getGraphics(); + + if (showAnnotation) + { + mg.translate(0, od.getSequencesHeight()); + or.drawGraph(mg, av.getAlignmentConservationAnnotation(), + av.getCharWidth(), od.getGraphHeight(), + od.getColumns(av.getRanges(), av.getColumnSelection())); + mg.translate(0, -od.getSequencesHeight()); + } + System.gc(); + + if (restart) + { + restart = false; + draw(showSequenceFeatures, showAnnotation, transferRenderer); + } + else + { + updaterunning = false; + lastMiniMe = miniMe; + } + } + + @Override + public void paintComponent(Graphics g) + { + if (restart) + { + 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); + } + +} diff --git a/src/jalview/gui/OverviewPanel.java b/src/jalview/gui/OverviewPanel.java index c530fdc..8a416bd 100755 --- a/src/jalview/gui/OverviewPanel.java +++ b/src/jalview/gui/OverviewPanel.java @@ -20,22 +20,26 @@ */ 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.OverviewDimensionsAllVisible; +import jalview.viewmodel.OverviewDimensionsWithHidden; -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 javax.swing.JMenuItem; 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,32 +50,15 @@ import javax.swing.JPanel; */ public class OverviewPanel extends JPanel implements Runnable { - 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; private AlignmentPanel ap; - // - private boolean resizing = false; - - // This is set true if the user resizes whilst - // the overview is being calculated - private boolean resizeAgain = false; - - // Can set different properties in this seqCanvas than - // main visible SeqCanvas - private SequenceRenderer sr; - - jalview.renderer.seqfeatures.FeatureRenderer fr; + private boolean showHidden = true; /** * Creates a new OverviewPanel object. @@ -83,17 +70,15 @@ public class OverviewPanel extends JPanel implements Runnable { this.av = alPanel.av; this.ap = alPanel; - setLayout(null); - sr = new SequenceRenderer(av); - sr.renderGaps = false; - sr.forOverview = true; - fr = new FeatureRenderer(ap); - - od = new OverviewDimensions(av.getRanges(), + od = new OverviewDimensionsWithHidden(av.getRanges(), (av.isShowAnnotation() && av .getAlignmentConservationAnnotation() != null)); + oviewCanvas = new OverviewCanvas(od, av); + setLayout(new BorderLayout()); + add(oviewCanvas, BorderLayout.CENTER); + addComponentListener(new ComponentAdapter() { @Override @@ -112,7 +97,8 @@ public class OverviewPanel extends JPanel implements Runnable @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 @@ -127,7 +113,14 @@ public class OverviewPanel extends JPanel implements Runnable @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 @@ -135,183 +128,95 @@ public class OverviewPanel extends JPanel implements Runnable ap.setScrollValues(od.getScrollCol(), od.getScrollRow()); } } + + @Override + public void mouseClicked(MouseEvent evt) + { + if (SwingUtilities.isRightMouseButton(evt)) + { + showPopupMenu(evt); + } + } }); + updateOverviewImage(); } - /** - * Updates the overview image when the related alignment panel is updated + /* + * Displays the popup menu and acts on user input */ - public void updateOverviewImage() + private void showPopupMenu(MouseEvent e) { - if (resizing) + JPopupMenu popup = new JPopupMenu(); + ActionListener menuListener = new ActionListener() { - resizeAgain = true; - return; - } - - resizing = true; - - if ((getWidth() > 0) && (getHeight() > 0)) - { - od.setWidth(getWidth()); - od.setHeight(getHeight()); - } - - setPreferredSize(new Dimension(od.getWidth(), od.getHeight())); - - Thread thread = new Thread(this); - thread.start(); - repaint(); - } - - @Override - public void run() - { - miniMe = null; - - if (av.isShowSequenceFeatures()) - { - fr.transferSettings(ap.getSeqPanel().seqCanvas.getFeatureRenderer()); - } - - // why do we need to set preferred size again? was set in - // updateOverviewImage - setPreferredSize(new Dimension(od.getWidth(), od.getHeight())); - - miniMe = new BufferedImage(od.getWidth(), od.getHeight(), - BufferedImage.TYPE_INT_RGB); - - Graphics mg = miniMe.getGraphics(); - mg.setColor(Color.orange); - mg.fillRect(0, 0, od.getWidth(), miniMe.getHeight()); - - // calculate sampleCol and sampleRow - // alignment width is max number of residues/bases - // alignment height is number of sequences - int alwidth = av.getAlignment().getWidth(); - int alheight = av.getAlignment().getAbsoluteHeight(); - - // sampleCol or sampleRow is the width/height allocated to each residue - // in particular, sometimes we may need more than one row/col of the - // BufferedImage allocated - // sampleCol is how much of a residue to assign to each pixel - // sampleRow is how many sequences to assign to each pixel - float sampleCol = alwidth / (float) od.getWidth(); - float sampleRow = alheight / (float) od.getSequencesHeight(); - - buildImage(sampleRow, sampleCol); - - // check for conservation annotation to make sure overview works for DNA too - if (av.isShowAnnotation() - && (av.getAlignmentConservationAnnotation() != null)) - { - renderer.updateFromAlignViewport(av); - for (int col = 0; col < od.getWidth() && !resizeAgain; col++) + @Override + public void actionPerformed(ActionEvent event) { - mg.translate(col, od.getSequencesHeight()); - renderer.drawGraph(mg, av.getAlignmentConservationAnnotation(), - av.getAlignmentConservationAnnotation().annotations, - (int) (sampleCol) + 1, od.getGraphHeight(), - (int) (col * sampleCol), (int) (col * sampleCol) + 1); - mg.translate(-col, -od.getSequencesHeight()); - + // switch on/off the hidden columns view + toggleHiddenColumns(); } - } - System.gc(); - - resizing = false; + }; + JMenuItem item; + popup.add(item = new JMenuItem(MessageManager + .getString("label.togglehidden"))); + item.addActionListener(menuListener); + popup.show(this, e.getX(), e.getY()); + } - if (resizeAgain) + private void toggleHiddenColumns() + { + if (showHidden) { - resizeAgain = false; - updateOverviewImage(); + showHidden = false; + od = new OverviewDimensionsAllVisible(av.getRanges(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null)); } else { - lastMiniMe = miniMe; + showHidden = true; + od = new OverviewDimensionsWithHidden(av.getRanges(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null)); } - - setBoxPosition(); + oviewCanvas.resetOviewDims(od); + updateOverviewImage(); } - /* - * Build the overview panel image + /** + * Updates the overview image when the related alignment panel is updated */ - private void buildImage(float sampleRow, float sampleCol) + public void updateOverviewImage() { - 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 ((getWidth() > 0) && (getHeight() > 0)) { - 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); - } + od.setWidth(getWidth()); + od.setHeight(getHeight()); } - } - /* - * Find the colour of a sequence at a specified column position - */ - private int getColumnColourFromSequence( - jalview.datamodel.SequenceI seq, - boolean hiddenRow, boolean hasHiddenCols, int lastcol, - FeatureColourFinder finder) - { - Color color = Color.white; + setPreferredSize(new Dimension(od.getWidth(), od.getHeight())); - if ((seq != null) && (seq.getLength() > lastcol)) + if (oviewCanvas.restartDraw()) { - color = sr.getResidueColour(seq, lastcol, finder); + return; } - if (hiddenRow - || (hasHiddenCols && !av.getColumnSelection() - .isVisible(lastcol))) - { - color = color.darker().darker(); - } + Thread thread = new Thread(this); + thread.start(); + repaint(); - return color.getRGB(); + } + + @Override + public void run() + { + oviewCanvas.draw(av.isShowSequenceFeatures(), + (av.isShowAnnotation() && av + .getAlignmentConservationAnnotation() != null), ap + .getSeqPanel().seqCanvas.getFeatureRenderer()); + setBoxPosition(); } /** @@ -325,36 +230,4 @@ public class OverviewPanel extends JPanel implements Runnable .getHiddenSequences(), av.getColumnSelection(), av.getRanges()); 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); - } } diff --git a/src/jalview/gui/OverviewRenderer.java b/src/jalview/gui/OverviewRenderer.java new file mode 100644 index 0000000..87937ba --- /dev/null +++ b/src/jalview/gui/OverviewRenderer.java @@ -0,0 +1,180 @@ +/* + * 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.gui; + +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentColsCollection; +import jalview.datamodel.AlignmentRowsCollection; +import jalview.datamodel.Annotation; +import jalview.datamodel.SequenceI; +import jalview.renderer.seqfeatures.FeatureColourFinder; +import jalview.viewmodel.OverviewDimensions; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.image.BufferedImage; + +public class OverviewRenderer +{ + private FeatureColourFinder finder; + + private SequenceRenderer sr; + + // image to render on + private BufferedImage miniMe; + + // raw number of pixels to allocate to each column + private float pixelsPerCol; + + // raw number of pixels to allocate to each row + private float pixelsPerSeq; + + public OverviewRenderer(SequenceRenderer seqRenderer, + FeatureColourFinder colfinder, OverviewDimensions od) + { + sr = seqRenderer; + finder = colfinder; + + pixelsPerCol = od.getPixelsPerCol(); + pixelsPerSeq = od.getPixelsPerSeq(); + miniMe = new BufferedImage(od.getWidth(), od.getHeight(), + BufferedImage.TYPE_INT_RGB); + } + + /** + * Draw alignment rows and columns onto an image + * + * @param rit + * Iterator over rows to be drawn + * @param cit + * Iterator over columns to be drawn + * @return image containing the drawing + */ + public BufferedImage draw(AlignmentRowsCollection rows, + AlignmentColsCollection cols) + { + int rgbcolor = Color.white.getRGB(); + int seqIndex = 0; + int pixelRow = 0; + for (int alignmentRow : rows) + { + // get details of this alignment row + boolean hidden = rows.isHidden(alignmentRow); + SequenceI seq = rows.getSequence(alignmentRow); + + // calculate where this row extends to in pixels + int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1, + miniMe.getHeight() - 1); + + int colIndex = 0; + int pixelCol = 0; + for (int alignmentCol : cols) + { + // calculate where this column extends to in pixels + int endCol = Math.min( + Math.round((colIndex + 1) * pixelsPerCol) - 1, + miniMe.getWidth() - 1); + + // determine the colour based on the sequence and column position + rgbcolor = getColumnColourFromSequence(seq, + hidden || cols.isHidden(alignmentCol), alignmentCol, finder); + + // fill in the appropriate number of pixels + for (int row = pixelRow; row <= endRow; ++row) + { + for (int col = pixelCol; col <= endCol; ++col) + { + miniMe.setRGB(col, row, rgbcolor); + } + } + + pixelCol = endCol + 1; + colIndex++; + } + pixelRow = endRow + 1; + seqIndex++; + } + return miniMe; + } + + /* + * Find the colour of a sequence at a specified column position + */ + private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq, + boolean isHidden, int lastcol, FeatureColourFinder finder) + { + Color color = Color.white; + + if ((seq != null) && (seq.getLength() > lastcol)) + { + color = sr.getResidueColour(seq, lastcol, finder); + } + + if (isHidden) + { + color = color.darker().darker(); + } + + return color.getRGB(); + } + + public void drawGraph(Graphics g, AlignmentAnnotation _aa, int charWidth, + int y, AlignmentColsCollection cols) + { + Annotation[] aa_annotations = _aa.annotations; + g.setColor(Color.white); + g.fillRect(0, 0, miniMe.getWidth(), y); + // g.setColor(new Color(0, 0, 180)); + + int height; + + int colIndex = 0; + int pixelCol = 0; + for (int alignmentCol : cols) + { + int endCol = Math.min(Math.round((colIndex + 1) * pixelsPerCol) - 1, + miniMe.getWidth() - 1); + + if (alignmentCol < aa_annotations.length + && aa_annotations[alignmentCol] != null) + { + if (aa_annotations[alignmentCol].colour == null) + { + g.setColor(Color.black); + } + else + { + g.setColor(aa_annotations[alignmentCol].colour); + } + + height = (int) ((aa_annotations[alignmentCol].value / _aa.graphMax) * y); + if (height > y) + { + height = y; + } + + g.fillRect(pixelCol, y - height, endCol - pixelCol + 1, height); + } + pixelCol = endCol + 1; + colIndex++; + } + } +} diff --git a/src/jalview/gui/SequenceRenderer.java b/src/jalview/gui/SequenceRenderer.java index 1c0420d..2a2a0cf 100755 --- a/src/jalview/gui/SequenceRenderer.java +++ b/src/jalview/gui/SequenceRenderer.java @@ -20,6 +20,7 @@ */ package jalview.gui; +import jalview.api.AlignViewportI; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.renderer.ResidueShaderI; @@ -34,7 +35,7 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer { final static int CHAR_TO_UPPER = 'A' - 'a'; - AlignViewport av; + AlignViewportI av; FontMetrics fm; @@ -57,7 +58,7 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer * * @param viewport */ - public SequenceRenderer(AlignViewport viewport) + public SequenceRenderer(AlignViewportI viewport) { this.av = viewport; } @@ -181,7 +182,7 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer drawBoxes(seq, start, end, y1); - if (av.validCharWidth) + if (av.isValidCharWidth()) { drawText(seq, start, end, y1); } diff --git a/src/jalview/viewmodel/AlignmentViewport.java b/src/jalview/viewmodel/AlignmentViewport.java index 47dceec..e0ffe33 100644 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@ -78,7 +78,7 @@ import jalview.workers.StrucConsensusThread; public abstract class AlignmentViewport implements AlignViewportI, CommandListener, VamsasSource { - protected ViewportRanges ranges; + final protected ViewportRanges ranges; protected ViewStyleI viewStyle = new ViewStyle(); @@ -95,6 +95,17 @@ public abstract class AlignmentViewport implements AlignViewportI, protected Deque redoList = new ArrayDeque(); /** + * alignment displayed in the viewport. Please use get/setter + */ + protected AlignmentI alignment; + + public AlignmentViewport(AlignmentI al) + { + setAlignment(al); + ranges = new ViewportRanges(al); + } + + /** * @param name * @see jalview.api.ViewStyleI#setFontName(java.lang.String) */ @@ -554,10 +565,7 @@ public abstract class AlignmentViewport implements AlignViewportI, viewStyle.setSeqNameItalics(default1); } - /** - * alignment displayed in the viewport. Please use get/setter - */ - protected AlignmentI alignment; + @Override public AlignmentI getAlignment() diff --git a/src/jalview/viewmodel/OverviewDimensions.java b/src/jalview/viewmodel/OverviewDimensions.java index 43680b5..50e1210 100644 --- a/src/jalview/viewmodel/OverviewDimensions.java +++ b/src/jalview/viewmodel/OverviewDimensions.java @@ -1,79 +1,31 @@ -/* - * 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.datamodel.AlignmentColsCollection; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.AlignmentRowsCollection; import jalview.datamodel.ColumnSelection; import jalview.datamodel.HiddenSequences; import java.awt.Graphics; -public class OverviewDimensions +public abstract class OverviewDimensions { - // Default width and height values - private static final int DEFAULT_GRAPH_HEIGHT = 20; - - private static final int MAX_WIDTH = 400; - - private static final int MIN_WIDTH = 120; - - private static final int MIN_SEQ_HEIGHT = 40; - - private static final int MAX_SEQ_HEIGHT = 300; - - // width of the overview panel - private int width; - - // height of sequences part of the overview panel - private int sequencesHeight; - - // height of the graphs part of the overview panel - private int graphHeight = DEFAULT_GRAPH_HEIGHT; - - // dimensions of box outlining current extent of view in alignment panel - // location of left side of box - private int boxX = -1; - - // location of bottom of box - private int boxY = -1; - // width of box - private int boxWidth = -1; - - // height of box - private int boxHeight = -1; - - // scroll position in viewport corresponding to boxX - private int scrollCol = -1; - - // scroll position in viewport corresponding to boxY - private int scrollRow = -1; + private static final int DEFAULT_GRAPH_HEIGHT = 20; + protected static final int MAX_WIDTH = 400; + protected static final int MIN_WIDTH = 120; + protected static final int MIN_SEQ_HEIGHT = 40; + protected static final int MAX_SEQ_HEIGHT = 300; + protected int width; + protected int sequencesHeight; + protected int graphHeight = DEFAULT_GRAPH_HEIGHT; + protected int boxX = -1; + protected int boxY = -1; + protected int boxWidth = -1; + protected int boxHeight = -1; + protected int scrollCol = -1; + protected int scrollRow = -1; - /** - * 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) { @@ -111,159 +63,6 @@ public class OverviewDimensions } /** - * 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 - */ - public void updateViewportFromMouse(int mousex, int mousey, - HiddenSequences hiddenSeqs, ColumnSelection hiddenCols, - ViewportRanges ranges) - { - int x = mousex; - int y = mousey; - - int alwidth = ranges.getAbsoluteAlignmentWidth(); - int alheight = ranges.getAbsoluteAlignmentHeight(); - - 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; - - // 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) - { - visXAsRes = hiddenCols.findColumnPosition(hiddenCols - .subtractVisibleColumns(vpwidth - 1, alwidth - 1)); - } - else - { - visXAsRes = scrollCol; - } - } - - // - // 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; - - // 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 visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq); - if (visYAsRes + vpheight - 1 > visAlignHeight) - { - // went past the end of the alignment, adjust backwards - if ((scrollRow + vpheight - 1) < visAlignHeight) - { - visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs - .subtractVisibleRows(vpheight - 1, alheight - 1)); - } - else - { - visYAsRes = scrollRow; - } - } - - // update scroll values - scrollCol = visXAsRes; - scrollRow = visYAsRes; - - } - - /** - * 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 - */ - public void setBoxPosition(HiddenSequences hiddenSeqs, - ColumnSelection hiddenCols, ViewportRanges ranges) - { - int alwidth = ranges.getAbsoluteAlignmentWidth(); - int alheight = ranges.getAbsoluteAlignmentHeight(); - - // 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()); - - // boxX, boxY is the x,y location equivalent to startRes, startSeq - boxX = Math.round((float) startRes * width / alwidth); - boxY = Math.round((float) startSeq * sequencesHeight / alheight); - - // boxWidth is the width in residues translated to pixels - // since the box includes both the start and end residues, add 1 to the - // difference - boxWidth = Math - .round((float) (endRes - startRes + 1) * width / alwidth); - // boxHeight is the height in sequences translated to pixels - boxHeight = Math.round((float) (endSeq - startSeq + 1) - * sequencesHeight - / alheight); - } - - /** * Draw the overview panel's viewport box on a graphics object * * @param g @@ -285,27 +84,21 @@ public class OverviewDimensions return scrollRow; } - // TODO should be removed, when unit test has mock Graphics object available - // to check boxX/boxY public int getBoxX() { return boxX; } - // TODO should be removed, when unit test has mock Graphics object available - // to check boxX/boxY public int getBoxY() { return boxY; } - // TODO should be removed, when unit test has mock Graphics object available public int getBoxWidth() { return boxWidth; } - // TODO should be removed, when unit test has mock Graphics object available public int getBoxHeight() { return boxHeight; @@ -340,4 +133,21 @@ public class OverviewDimensions { return graphHeight; } -} + + public abstract void updateViewportFromMouse(int mousex, int mousey, + HiddenSequences hiddenSeqs, ColumnSelection hiddenCols, + ViewportRanges ranges); + + public abstract void setBoxPosition(HiddenSequences hiddenSeqs, + ColumnSelection hiddenCols, ViewportRanges ranges); + + public abstract AlignmentColsCollection getColumns( + ViewportRanges ranges, ColumnSelection hiddenCols); + + public abstract AlignmentRowsCollection getRows( + ViewportRanges ranges, AlignmentI al); + + public abstract float getPixelsPerCol(); + + public abstract float getPixelsPerSeq(); +} \ No newline at end of file diff --git a/src/jalview/viewmodel/OverviewDimensionsAllVisible.java b/src/jalview/viewmodel/OverviewDimensionsAllVisible.java new file mode 100644 index 0000000..21f0be6 --- /dev/null +++ b/src/jalview/viewmodel/OverviewDimensionsAllVisible.java @@ -0,0 +1,165 @@ +package jalview.viewmodel; + +import jalview.datamodel.AlignmentColsCollection; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.AlignmentRowsCollection; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.HiddenSequences; + +public class OverviewDimensionsAllVisible extends OverviewDimensions +{ + private float pixelsPerCol; + + private float pixelsPerSeq; + + public OverviewDimensionsAllVisible(ViewportRanges ranges, + boolean showAnnotationPanel) + { + super(ranges, showAnnotationPanel); + + int alwidth = ranges.getVisibleAlignmentWidth(); + int alheight = ranges.getVisibleAlignmentHeight(); + + pixelsPerCol = (float) width / alwidth; + pixelsPerSeq = (float) sequencesHeight / alheight; + } + + @Override + public void updateViewportFromMouse(int mousex, int mousey, + HiddenSequences hiddenSeqs, ColumnSelection hiddenCols, + ViewportRanges ranges) + { + int x = mousex; + int y = mousey; + + int alwidth = ranges.getVisibleAlignmentWidth(); + int alheight = ranges.getVisibleAlignmentHeight(); + + 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; + + 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) + { + xAsRes = alwidth - vpwidth; + } + else + { + xAsRes = scrollCol; + } + } + + + // + // 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; + + if (yAsSeq + vpheight > alheight) + { + // went past the end of the alignment, adjust backwards + if ((scrollRow + vpheight - 1) < alheight) + { + yAsSeq = alheight - vpheight; + } + else + { + yAsSeq = scrollRow; + } + } + + // update scroll values + scrollCol = xAsRes; + scrollRow = yAsSeq; + + } + + @Override + public void setBoxPosition(HiddenSequences hiddenSeqs, + ColumnSelection hiddenCols, ViewportRanges ranges) + { + int alwidth = ranges.getVisibleAlignmentWidth(); + int alheight = ranges.getVisibleAlignmentHeight(); + + // 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(); + + // boxX, boxY is the x,y location equivalent to startRes, startSeq + boxX = Math.round((float) startRes * width / alwidth); + boxY = Math.round((float) startSeq * sequencesHeight / alheight); + + // boxWidth is the width in residues translated to pixels + // since the box includes both the start and end residues, add 1 to the + // difference + boxWidth = Math + .round((float) (endRes - startRes + 1) * width / alwidth); + // boxHeight is the height in sequences translated to pixels + boxHeight = Math.round((float) (endSeq - startSeq + 1) + * sequencesHeight / alheight); + + } + + @Override + public AlignmentColsCollection getColumns(ViewportRanges ranges, + ColumnSelection hiddenCols) + { + return new AlignmentColsCollection(0, + ranges.getVisibleAlignmentWidth() - 1, hiddenCols); + } + + @Override + public AlignmentRowsCollection getRows(ViewportRanges ranges, + AlignmentI al) + { + return new AlignmentRowsCollection(0, + ranges.getVisibleAlignmentHeight() - 1, al); + } + + @Override + public float getPixelsPerCol() + { + return pixelsPerCol; + } + + @Override + public float getPixelsPerSeq() + { + return pixelsPerSeq; + } +} diff --git a/src/jalview/viewmodel/OverviewDimensionsWithHidden.java b/src/jalview/viewmodel/OverviewDimensionsWithHidden.java new file mode 100644 index 0000000..575167a --- /dev/null +++ b/src/jalview/viewmodel/OverviewDimensionsWithHidden.java @@ -0,0 +1,239 @@ +/* + * 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.datamodel.AlignmentColsCollection; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.AlignmentRowsCollection; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.HiddenSequences; + +public class OverviewDimensionsWithHidden extends OverviewDimensions +{ + private float pixelsPerCol; + + private float pixelsPerSeq; + + /** + * 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 OverviewDimensionsWithHidden(ViewportRanges ranges, + boolean showAnnotationPanel) + { + super(ranges, showAnnotationPanel); + + int alwidth = ranges.getAbsoluteAlignmentWidth(); + int alheight = ranges.getAbsoluteAlignmentHeight(); + + pixelsPerCol = (float) width / alwidth; + pixelsPerSeq = (float) sequencesHeight / alheight; + } + + /** + * 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, ColumnSelection hiddenCols, + ViewportRanges ranges) + { + int x = mousex; + int y = mousey; + + int alwidth = ranges.getAbsoluteAlignmentWidth(); + int alheight = ranges.getAbsoluteAlignmentHeight(); + + 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; + + // 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) + { + visXAsRes = hiddenCols.findColumnPosition(hiddenCols + .subtractVisibleColumns(vpwidth - 1, alwidth - 1)); + } + else + { + visXAsRes = scrollCol; + } + } + + // + // 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; + + // 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) + { + visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs + .subtractVisibleRows(vpheight - 1, alheight - 1)); + } + else + { + visYAsSeq = scrollRow; + } + } + + // update scroll values + scrollCol = visXAsRes; + scrollRow = visYAsSeq; + + } + + /** + * 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, + ColumnSelection hiddenCols, ViewportRanges ranges) + { + int alwidth = ranges.getAbsoluteAlignmentWidth(); + int alheight = ranges.getAbsoluteAlignmentHeight(); + + // 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()); + + // boxX, boxY is the x,y location equivalent to startRes, startSeq + boxX = Math.round((float) startRes * width / alwidth); + boxY = Math.round((float) startSeq * sequencesHeight / alheight); + + // boxWidth is the width in residues translated to pixels + // since the box includes both the start and end residues, add 1 to the + // difference + boxWidth = Math + .round((float) (endRes - startRes + 1) * width / alwidth); + // boxHeight is the height in sequences translated to pixels + boxHeight = Math.round((float) (endSeq - startSeq + 1) + * sequencesHeight + / alheight); + } + + @Override + public AlignmentColsCollection getColumns(ViewportRanges ranges, + ColumnSelection hiddenCols) + { + return new AlignmentColsCollection(0, + ranges.getAbsoluteAlignmentWidth() - 1, + hiddenCols); + } + + @Override + public AlignmentRowsCollection getRows(ViewportRanges ranges, + AlignmentI al) + { + return new AlignmentRowsCollection(0, + ranges.getAbsoluteAlignmentHeight() - 1, + al); + } + + @Override + public float getPixelsPerCol() + { + return pixelsPerCol; + } + + @Override + public float getPixelsPerSeq() + { + return pixelsPerSeq; + } +} diff --git a/src/jalview/viewmodel/ViewportRanges.java b/src/jalview/viewmodel/ViewportRanges.java index c91d2d9..18703b4 100644 --- a/src/jalview/viewmodel/ViewportRanges.java +++ b/src/jalview/viewmodel/ViewportRanges.java @@ -79,6 +79,23 @@ public class ViewportRanges extends ViewportProperties } /** + * Get alignment width in cols, excluding hidden cols + */ + public int getVisibleAlignmentWidth() + { + // TODO need access to hidden columns here + return al.getWidth(); // - hidden columns + } + + /** + * Get alignment height in rows, excluding hidden rows + */ + public int getVisibleAlignmentHeight() + { + return al.getHeight(); + } + + /** * Set first residue visible in the viewport * * @param res diff --git a/test/jalview/datamodel/AllColsIteratorTest.java b/test/jalview/datamodel/AllColsIteratorTest.java new file mode 100644 index 0000000..ee82340 --- /dev/null +++ b/test/jalview/datamodel/AllColsIteratorTest.java @@ -0,0 +1,85 @@ +/* + * 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.datamodel; + +import static org.testng.Assert.assertTrue; + +import java.util.NoSuchElementException; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class AllColsIteratorTest +{ + ColumnSelection hiddenCols; + + @BeforeClass + public void setup() + { + hiddenCols = new ColumnSelection(); + hiddenCols.hideColumns(2,4); + } + + + /* + * Test iterator iterates through collection correctly + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNext() + { + AllColsIterator it = new AllColsIterator(0, 3, hiddenCols); + int count = 0; + while (it.hasNext()) + { + it.next(); + count++; + } + assertTrue(count == 4, "hasNext() is false after 4 iterations"); + } + + /* + * Test iterator throws NoSuchElementException at end of iteration + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNext() throws NoSuchElementException + { + AllColsIterator it = new AllColsIterator(0, 3, hiddenCols); + while (it.hasNext()) + { + it.next(); + } + it.next(); + } + + /* + * Test iterator throws UnsupportedOperationException on call to remove + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { UnsupportedOperationException.class }) + public void testRemove() throws UnsupportedOperationException + { + AllColsIterator it = new AllColsIterator(0, 3, hiddenCols); + it.remove(); + } +} diff --git a/test/jalview/datamodel/AllRowsIteratorTest.java b/test/jalview/datamodel/AllRowsIteratorTest.java new file mode 100644 index 0000000..fd1d29d --- /dev/null +++ b/test/jalview/datamodel/AllRowsIteratorTest.java @@ -0,0 +1,113 @@ +/* + * 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.datamodel; + +import static org.testng.Assert.assertTrue; + +import jalview.analysis.AlignmentGenerator; + +import java.util.Hashtable; +import java.util.NoSuchElementException; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class AllRowsIteratorTest +{ + AlignmentI al; + + Hashtable hiddenRepSequences = new Hashtable(); + + @BeforeClass + public void setup() + { + // create random alignment + AlignmentGenerator gen = new AlignmentGenerator(false); + al = gen.generate(20, 15, 123, 5, 5); + if (!hiddenRepSequences.isEmpty()) + { + al.getHiddenSequences().showAll(hiddenRepSequences); + } + hideSequences(2, 4); + } + + /* + * Test iterator iterates through collection correctly + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNext() + { + AllRowsIterator it = new AllRowsIterator(0, 3, al); + int count = 0; + while (it.hasNext()) + { + it.next(); + count++; + } + assertTrue(count == 4, "hasNext() is false after 4 iterations"); + } + + /* + * Test iterator throws NoSuchElementException at end of iteration + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNext() throws NoSuchElementException + { + AllRowsIterator it = new AllRowsIterator(0, 3, al); + while (it.hasNext()) + { + it.next(); + } + it.next(); + } + + /* + * Test iterator throws UnsupportedOperationException on call to remove + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { UnsupportedOperationException.class }) + public void testRemove() throws UnsupportedOperationException + { + AllRowsIterator it = new AllRowsIterator(0, 3, al); + it.remove(); + } + + + /* + * 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 --git a/test/jalview/datamodel/VisibleColsIteratorTest.java b/test/jalview/datamodel/VisibleColsIteratorTest.java new file mode 100644 index 0000000..c07b3c9 --- /dev/null +++ b/test/jalview/datamodel/VisibleColsIteratorTest.java @@ -0,0 +1,198 @@ +/* + * 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.datamodel; + +import static org.testng.Assert.assertTrue; + +import java.util.NoSuchElementException; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class VisibleColsIteratorTest +{ + ColumnSelection hiddenCols; + + ColumnSelection hiddenColsAtStart; + + @BeforeClass + public void setup() + { + hiddenCols = new ColumnSelection(); + hiddenCols.hideColumns(2, 4); + + hiddenColsAtStart = new ColumnSelection(); + hiddenColsAtStart.hideColumns(0, 2); + } + + /* + * Test iterator iterates correctly through the columns + * when alignment has hidden cols + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNextWithHidden() + { + VisibleColsIterator it = new VisibleColsIterator(0, 6, hiddenCols); + int count = 0; + while (it.hasNext()) + { + it.next(); + count++; + } + assertTrue(count == 4, "hasNext() is false after 4 iterations"); + } + + /* + * Test iterator iterates correctly through the columns + * when alignment has no hidden cols + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNextNoHidden() + { + VisibleColsIterator it2 = new VisibleColsIterator(0, 3, + new ColumnSelection()); + int count = 0; + while (it2.hasNext()) + { + it2.next(); + count++; + } + assertTrue(count == 4, "hasNext() is false after 4 iterations"); + } + + /* + * Test iterator iterates correctly through the columns + * when alignment has hidden cols at start + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNextStartHidden() + { + VisibleColsIterator it3 = new VisibleColsIterator(0, 6, + hiddenColsAtStart); + int count = 0; + while (it3.hasNext()) + { + it3.next(); + count++; + } + assertTrue(count == 4, "hasNext() is false after 4 iterations"); + } + + /* + * Test iterator iterates correctly through the columns + * when alignment has hidden cols at end + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNextEndHidden() + { + VisibleColsIterator it4 = new VisibleColsIterator(0, 4, hiddenCols); + int count = 0; + while (it4.hasNext()) + { + it4.next(); + count++; + } + assertTrue(count == 2, "hasNext() is false after 2 iterations"); + + } + + /* + * Test iterator always throws NoSuchElementException at end of iteration + * when alignment has hidden cols + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNextWithHidden() throws NoSuchElementException + { + VisibleColsIterator it = new VisibleColsIterator(0, 3, hiddenCols); + while (it.hasNext()) + { + it.next(); + } + it.next(); + } + + /* + * Test iterator always throws NoSuchElementException at end of iteration + * when alignment has no hidden cols + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNextNoHidden() throws NoSuchElementException + { + VisibleColsIterator it2 = new VisibleColsIterator(0, 3, + new ColumnSelection()); + while (it2.hasNext()) + { + it2.next(); + } + it2.next(); + } + + /* + * Test iterator always throws NoSuchElementException at end of iteration + * when alignment has hidden cols at start + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNextStartHidden() throws NoSuchElementException + { + VisibleColsIterator it3 = new VisibleColsIterator(0, 6, + hiddenColsAtStart); + while (it3.hasNext()) + { + it3.next(); + } + it3.next(); + } + + /* + * Test iterator always throws NoSuchElementException at end of iteration + * when alignment has hidden cols at end + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNextEndHidden() throws NoSuchElementException + { + VisibleColsIterator it4 = new VisibleColsIterator(0, 4, hiddenCols); + while (it4.hasNext()) + { + it4.next(); + } + it4.next(); + } + + /* + * Test calls to remove throw UnsupportedOperationException + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { UnsupportedOperationException.class }) + public void testRemove() throws UnsupportedOperationException + { + VisibleColsIterator it = new VisibleColsIterator(0, 3, hiddenCols); + it.remove(); + } +} diff --git a/test/jalview/datamodel/VisibleRowsIteratorTest.java b/test/jalview/datamodel/VisibleRowsIteratorTest.java new file mode 100644 index 0000000..da93dab --- /dev/null +++ b/test/jalview/datamodel/VisibleRowsIteratorTest.java @@ -0,0 +1,233 @@ +/* + * 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.datamodel; + +import static org.testng.Assert.assertTrue; + +import jalview.analysis.AlignmentGenerator; + +import java.util.Hashtable; +import java.util.NoSuchElementException; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class VisibleRowsIteratorTest +{ + AlignmentI al; + + AlignmentI al2; + + AlignmentI al3; + + Hashtable hiddenRepSequences = new Hashtable(); + + Hashtable hiddenRepSequences2 = new Hashtable(); + + @BeforeClass + public void setup() + { + // create random alignment + AlignmentGenerator gen = new AlignmentGenerator(false); + al = gen.generate(20, 15, 123, 5, 5); + if (!hiddenRepSequences.isEmpty()) + { + al.getHiddenSequences().showAll(hiddenRepSequences); + } + hideSequences(al, hiddenRepSequences, 2, 4); + + al2 = gen.generate(20, 15, 123, 5, 5); + if (!hiddenRepSequences2.isEmpty()) + { + al2.getHiddenSequences().showAll(hiddenRepSequences2); + } + hideSequences(al2, hiddenRepSequences2, 0, 2); + + al3 = gen.generate(20, 15, 123, 5, 5); + } + + /* + * Test iterator iterates correctly through the rows + * when alignment has hidden rows + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNextWithHidden() + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 6, al); + int count = 0; + while (it.hasNext()) + { + it.next(); + count++; + } + assertTrue(count == 4, "hasNext() is false after 4 iterations"); + } + + /* + * Test iterator iterates correctly through the rows + * when alignment has no hidden rows + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNextNoHidden() + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al3); + int count = 0; + while (it.hasNext()) + { + it.next(); + count++; + } + assertTrue(count == 4, "hasNext() is false after 4 iterations"); + } + + /* + * Test iterator iterates correctly through the rows + * when alignment has hidden rows at start + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNextStartHidden() + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 6, al2); + int count = 0; + while (it.hasNext()) + { + it.next(); + count++; + } + assertTrue(count == 4, "hasNext() is false after 4 iterations"); + } + + /* + * Test iterator iterates correctly through the rows + * when alignment has hidden rows at end + */ + @Test(groups = { "Functional" }) + public void testHasNextAndNextEndHidden() + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 4, al); + int count = 0; + while (it.hasNext()) + { + it.next(); + count++; + } + assertTrue(count == 2, "hasNext() is false after 2 iterations"); + } + + /* + * Test iterator always throws NoSuchElementException at end of iteration + * when alignment has hidden rows + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNextWithHidden() throws NoSuchElementException + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al); + while (it.hasNext()) + { + it.next(); + } + it.next(); + } + + /* + * Test iterator always throws NoSuchElementException at end of iteration + * when alignment has no hidden rows + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNextNoHidden() throws NoSuchElementException + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al3); + while (it.hasNext()) + { + it.next(); + } + it.next(); + } + + /* + * Test iterator always throws NoSuchElementException at end of iteration + * when alignment has hidden rows at start + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNextStartHidden() throws NoSuchElementException + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al2); + while (it.hasNext()) + { + it.next(); + } + it.next(); + } + + /* + * Test iterator always throws NoSuchElementException at end of iteration + * when alignment has hidden rows at end + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { NoSuchElementException.class }) + public void testLastNextEndHidden() throws NoSuchElementException + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 4, al); + while (it.hasNext()) + { + it.next(); + } + it.next(); + } + + /* + * Test calls to remove throw UnsupportedOperationException + */ + @Test( + groups = { "Functional" }, + expectedExceptions = { UnsupportedOperationException.class }) + public void testRemove() throws UnsupportedOperationException + { + VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al); + it.remove(); + } + + /* + * Hide sequences between start and end + */ + private void hideSequences(AlignmentI alignment, + Hashtable hiddenRepSequences, + int start, int end) + { + SequenceI[] allseqs = alignment.getSequencesArray(); + SequenceGroup theseSeqs = new SequenceGroup(); + + for (int i = start; i <= end; i++) + { + theseSeqs.addSequence(allseqs[i], false); + alignment.getHiddenSequences().hideSequence(allseqs[i]); + } + + hiddenRepSequences.put(allseqs[start], theseSeqs); + } +} diff --git a/test/jalview/viewmodel/OverviewDimensionsTest.java b/test/jalview/viewmodel/OverviewDimensionsTest.java index 398fec3..dc414fb 100644 --- a/test/jalview/viewmodel/OverviewDimensionsTest.java +++ b/test/jalview/viewmodel/OverviewDimensionsTest.java @@ -42,7 +42,7 @@ import org.testng.annotations.Test; public class OverviewDimensionsTest { AlignmentI al; - OverviewDimensions od; + OverviewDimensionsWithHidden od; // cached widths and heights int boxWidth; @@ -86,7 +86,7 @@ public class OverviewDimensionsTest ColumnSelection hiddenCols = new ColumnSelection(); - od = new OverviewDimensions(vpranges, true); + od = new OverviewDimensionsWithHidden(vpranges, true); // Initial box sizing - default path through code od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges); @@ -136,7 +136,7 @@ public class OverviewDimensionsTest Alignment al1 = new Alignment(seqs1); ViewportRanges props = new ViewportRanges(al1); - OverviewDimensions od = new OverviewDimensions(props, true); + OverviewDimensions od = new OverviewDimensionsWithHidden(props, true); int scaledHeight = 267; assertEquals(od.getGraphHeight(), defaultGraphHeight); assertEquals(od.getSequencesHeight(), scaledHeight); @@ -148,7 +148,7 @@ public class OverviewDimensionsTest Alignment al2 = new Alignment(seqs2); props = new ViewportRanges(al2); - od = new OverviewDimensions(props, true); + od = new OverviewDimensionsWithHidden(props, true); int scaledWidth = 300; assertEquals(od.getGraphHeight(), defaultGraphHeight); assertEquals(od.getSequencesHeight(), maxSeqHeight); @@ -161,7 +161,7 @@ public class OverviewDimensionsTest Alignment al3 = new Alignment(seqs3); props = new ViewportRanges(al3); - od = new OverviewDimensions(props, true); + od = new OverviewDimensionsWithHidden(props, true); assertEquals(od.getGraphHeight(), defaultGraphHeight); assertEquals(od.getSequencesHeight(), minSeqHeight); assertEquals(od.getWidth(), maxWidth); @@ -173,7 +173,7 @@ public class OverviewDimensionsTest Alignment al4 = new Alignment(seqs4); props = new ViewportRanges(al4); - od = new OverviewDimensions(props, true); + od = new OverviewDimensionsWithHidden(props, true); assertEquals(od.getGraphHeight(), defaultGraphHeight); assertEquals(od.getSequencesHeight(), maxSeqHeight); assertEquals(od.getWidth(), minWidth); @@ -182,7 +182,7 @@ public class OverviewDimensionsTest Alignment al5 = new Alignment(seqs4); props = new ViewportRanges(al5); - od = new OverviewDimensions(props, false); + od = new OverviewDimensionsWithHidden(props, false); assertEquals(od.getGraphHeight(), 0); assertEquals(od.getSequencesHeight(), maxSeqHeight); assertEquals(od.getWidth(), minWidth); @@ -988,7 +988,7 @@ public class OverviewDimensionsTest /* * Mouse click as position x,y in overview window */ - private void mouseClick(OverviewDimensions od, int x, int y) + private void mouseClick(OverviewDimensionsWithHidden od, int x, int y) { od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols, vpranges);