}
case KeyEvent.VK_PAGE_UP:
- if (viewport.getWrapAlignment())
- {
- ranges.scrollUp(true);
- }
- else
- {
- ranges.pageUp();
- }
+ ranges.pageUp();
break;
case KeyEvent.VK_PAGE_DOWN:
- if (viewport.getWrapAlignment())
- {
- ranges.scrollUp(false);
- }
- else
- {
- ranges.pageDown();
- }
+ ranges.pageDown();
break;
case KeyEvent.VK_Z:
}
Frame frame = new Frame();
- OverviewPanel overview = new OverviewPanel(alignPanel);
+ final OverviewPanel overview = new OverviewPanel(alignPanel);
frame.add(overview);
// +50 must allow for applet frame window
jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
@Override
public void windowClosing(WindowEvent e)
{
+ overview.dispose();
if (ap != null)
{
ap.setOverviewPanel(null);
sendViewPosition();
}
- private void adjustVertical(int offy)
+ private void adjustVertical(int newY)
{
- int oldX = vpRanges.getStartRes();
- int oldwidth = vpRanges.getViewportWidth();
- int oldY = vpRanges.getStartSeq();
- int oldheight = vpRanges.getViewportHeight();
-
if (av.getWrapAlignment())
{
- int rowSize = seqPanel.seqCanvas
- .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
-
- // if we're scrolling to the position we're already at, stop
- // this prevents infinite recursion of events when the scroll/viewport
- // ranges values are the same
- if ((offy * rowSize == oldX) && (oldwidth == rowSize))
+ /*
+ * if we're scrolling to the position we're already at, stop
+ * this prevents infinite recursion of events when the scroll/viewport
+ * ranges values are the same
+ */
+ int oldX = vpRanges.getStartRes();
+ int oldY = vpRanges.getWrappedScrollPosition(oldX);
+ if (oldY == newY)
{
return;
}
- else if (offy > -1)
+ if (newY > -1)
{
- vpRanges.setViewportStartAndWidth(offy * rowSize, rowSize);
+ /*
+ * limit page up/down to one width's worth of positions
+ */
+ int rowSize = vpRanges.getViewportWidth();
+ int newX = newY > oldY ? oldX + rowSize : oldX - rowSize;
+ vpRanges.setViewportStartAndWidth(Math.max(0, newX), rowSize);
}
}
else
{
int height = seqPanel.seqCanvas.getHeight() / av.getCharHeight();
+ int oldY = vpRanges.getStartSeq();
+ int oldheight = vpRanges.getViewportHeight();
// if we're scrolling to the position we're already at, stop
// this prevents infinite recursion of events when the scroll/viewport
// ranges values are the same
- if ((offy == oldY) && (height == oldheight))
+ if ((newY == oldY) && (height == oldheight))
{
return;
}
- vpRanges.setViewportStartAndHeight(offy, height);
+ vpRanges.setViewportStartAndHeight(newY, height);
}
if (av.getWrapAlignment() || !fastPaint)
{
}
- /*
+ /**
* Set vertical scroll bar parameters for wrapped panel
- * @param res
- * the residue to scroll to
+ *
+ * @param topLeftColumn
+ * the column position at top left (0..)
*/
- private void setScrollingForWrappedPanel(int res)
+ private void setScrollingForWrappedPanel(int topLeftColumn)
{
- // get the width of the alignment in residues
- int maxwidth = av.getAlignment().getWidth();
- if (av.hasHiddenColumns())
- {
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
- }
+ int scrollPosition = vpRanges.getWrappedScrollPosition(topLeftColumn);
+ int maxScroll = vpRanges.getWrappedMaxScroll(topLeftColumn);
- // get the width of the canvas in residues
- int canvasWidth = seqPanel.seqCanvas
- .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
- if (canvasWidth > 0)
- {
- // position we want to scroll to is number of canvasWidth's to get there
- int current = res / canvasWidth;
-
- // max scroll position: add one because extent is 1 and scrollbar value
- // can only be set to at most max - extent
- int max = maxwidth / canvasWidth + 1;
- vscroll.setUnitIncrement(1);
- vscroll.setValues(current, 1, 0, max);
- }
+ /*
+ * a scrollbar's value can be set to at most (maximum-extent)
+ * so we add extent (1) to the maxScroll value
+ */
+ vscroll.setUnitIncrement(1);
+ vscroll.setValues(scrollPosition, 1, 0, maxScroll + 1);
}
protected Panel sequenceHolderPanel = new Panel();
float mm[] = fr.getMinMax().get(type)[0];
min = mm[0];
max = mm[1];
+ threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
oldcs = fr.getFeatureColours().get(type);
if (oldcs.isGraduatedColour())
{
+ threshline.value = oldcs.getThreshold();
cs = new FeatureColour((FeatureColour) oldcs, min, max);
}
else
thresholdValue.setText("");
}
- else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
- && threshline == null)
- {
- // todo visual indication of feature threshold
- threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
- "Threshold", Color.black);
- }
-
if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
{
adjusting = true;
public void fastPaint(int vertical)
{
- if (gg == null)
+ if (gg == null || av.getWrapAlignment())
{
repaint();
return;
void drawIds(int starty, int endy)
{
- // hardwired italic IDs in applet currently
- Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
- .getFont().getSize());
- // temp variable for speed
avcharHeight = av.getCharHeight();
- gg.setFont(italic);
-
Color currentColor = Color.white;
Color currentTextColor = Color.black;
final boolean doHiddenCheck = av.isDisplayReferenceSeq()
- || av.hasHiddenRows(), hiddenRows = av.hasHiddenRows()
- && av.getShowHiddenMarkers();
+ || av.hasHiddenRows();
+ boolean hiddenRows = av.hasHiddenRows() && av.getShowHiddenMarkers();
if (av.getWrapAlignment())
{
- int maxwidth = av.getAlignment().getWidth();
- int alheight = av.getAlignment().getHeight();
+ drawIdsWrapped(starty, doHiddenCheck, hiddenRows);
+ return;
+ }
- if (av.hasHiddenColumns())
+ // Now draw the id strings
+ SequenceI seq;
+ for (int i = starty; i <= endy; i++)
+ {
+ seq = av.getAlignment().getSequenceAt(i);
+ if (seq == null)
{
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
+ continue;
+ }
+ // hardwired italic IDs in applet currently
+ Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
+ .getFont().getSize());
+ gg.setFont(italic);
+ // boolean isrep=false;
+ if (doHiddenCheck)
+ {
+ // isrep =
+ setHiddenFont(seq);
}
- int annotationHeight = 0;
- AnnotationLabels labels = null;
-
- if (av.isShowAnnotation())
+ // Selected sequence colours
+ if ((searchResults != null) && searchResults.contains(seq))
{
- AnnotationPanel ap = new AnnotationPanel(av);
- annotationHeight = ap.adjustPanelHeight();
- labels = new AnnotationLabels(av);
+ currentColor = Color.black;
+ currentTextColor = Color.white;
}
- int hgap = avcharHeight;
- if (av.getScaleAboveWrapped())
+ else if ((av.getSelectionGroup() != null)
+ && av.getSelectionGroup().getSequences(null).contains(seq))
+ {
+ currentColor = Color.lightGray;
+ currentTextColor = Color.black;
+ }
+ else
{
- hgap += avcharHeight;
+ currentColor = av.getSequenceColour(seq);
+ currentTextColor = Color.black;
}
- int cHeight = alheight * avcharHeight + hgap + annotationHeight;
+ gg.setColor(currentColor);
+ // TODO: isrep could be used to highlight the representative in a
+ // different way
+ gg.fillRect(0, (i - starty) * avcharHeight, getSize().width,
+ avcharHeight);
+ gg.setColor(currentTextColor);
- int rowSize = av.getRanges().getEndRes()
- - av.getRanges().getStartRes();
- // Draw the rest of the panels
- for (int ypos = hgap, row = av.getRanges().getStartRes(); (ypos <= getSize().height)
- && (row < maxwidth); ypos += cHeight, row += rowSize)
+ gg.drawString(seq.getDisplayId(av.getShowJVSuffix()), 0,
+ (((i - starty) * avcharHeight) + avcharHeight)
+ - (avcharHeight / 5));
+
+ if (hiddenRows)
{
- for (int i = starty; i < alheight; i++)
- {
+ drawMarker(i, starty, 0);
+ }
+ }
+ }
- SequenceI s = av.getAlignment().getSequenceAt(i);
- gg.setFont(italic);
- if (doHiddenCheck)
- {
- setHiddenFont(s);
- }
- drawIdString(gg, hiddenRows, s, i, 0, ypos);
- }
+ /**
+ * Draws sequence ids in wrapped mode
+ *
+ * @param starty
+ * @param doHiddenCheck
+ * @param hiddenRows
+ */
+ protected void drawIdsWrapped(int starty, final boolean doHiddenCheck,
+ boolean hiddenRows)
+ {
+ int maxwidth = av.getAlignment().getWidth();
+ int alheight = av.getAlignment().getHeight();
- if (labels != null)
- {
- gg.translate(0, ypos + (alheight * avcharHeight));
- labels.drawComponent(gg, getSize().width);
- gg.translate(0, -ypos - (alheight * avcharHeight));
- }
+ if (av.hasHiddenColumns())
+ {
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
+ }
- }
+ int annotationHeight = 0;
+ AnnotationLabels labels = null;
+
+ if (av.isShowAnnotation())
+ {
+ AnnotationPanel ap = new AnnotationPanel(av);
+ annotationHeight = ap.adjustPanelHeight();
+ labels = new AnnotationLabels(av);
}
- else
+ int hgap = avcharHeight;
+ if (av.getScaleAboveWrapped())
{
- // Now draw the id strings
- SequenceI seq;
- for (int i = starty; i <= endy; i++)
- {
+ hgap += avcharHeight;
+ }
- seq = av.getAlignment().getSequenceAt(i);
- if (seq == null)
- {
- continue;
- }
- gg.setFont(italic);
- // boolean isrep=false;
- if (doHiddenCheck)
- {
- // isrep =
- setHiddenFont(seq);
- }
+ int cHeight = alheight * avcharHeight + hgap + annotationHeight;
- // Selected sequence colours
- if ((searchResults != null) && searchResults.contains(seq))
- {
- currentColor = Color.black;
- currentTextColor = Color.white;
- }
- else if ((av.getSelectionGroup() != null)
- && av.getSelectionGroup().getSequences(null).contains(seq))
- {
- currentColor = Color.lightGray;
- currentTextColor = Color.black;
- }
- else
- {
- currentColor = av.getSequenceColour(seq);
- currentTextColor = Color.black;
- }
+ int rowSize = av.getRanges().getViewportWidth();
- gg.setColor(currentColor);
- // TODO: isrep could be used to highlight the representative in a
- // different way
- gg.fillRect(0, (i - starty) * avcharHeight, getSize().width,
- avcharHeight);
- gg.setColor(currentTextColor);
+ // hardwired italic IDs in applet currently
+ Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
+ .getFont().getSize());
+ gg.setFont(italic);
- gg.drawString(seq.getDisplayId(av.getShowJVSuffix()), 0,
- (((i - starty) * avcharHeight) + avcharHeight)
- - (avcharHeight / 5));
+ /*
+ * draw repeating sequence ids until out of sequence data or
+ * out of visible space, whichever comes first
+ */
+ int ypos = hgap;
+ int row = av.getRanges().getStartRes();
+ while ((ypos <= getHeight()) && (row < maxwidth))
+ {
+ for (int i = starty; i < alheight; i++)
+ {
- if (hiddenRows)
+ SequenceI s = av.getAlignment().getSequenceAt(i);
+ // gg.setFont(italic);
+ if (doHiddenCheck)
{
- drawMarker(i, starty, 0);
+ setHiddenFont(s);
}
+ drawIdString(gg, hiddenRows, s, i, 0, ypos);
}
+
+ if (labels != null)
+ {
+ gg.translate(0, ypos + (alheight * avcharHeight));
+ labels.drawComponent(gg, getSize().width);
+ gg.translate(0, -ypos - (alheight * avcharHeight));
+ }
+ ypos += cHeight;
+ row += rowSize;
}
}
return false;
}
+ /**
+ * Respond to viewport range changes (e.g. alignment panel was scrolled). Both
+ * scrolling and resizing change viewport ranges. Scrolling changes both start
+ * and end points, but resize only changes end values. Here we only want to
+ * fastpaint on a scroll, with resize using a normal paint, so scroll events
+ * are identified as changes to the horizontal or vertical start value.
+ * <p>
+ * In unwrapped mode, only responds to a vertical scroll, as horizontal scroll
+ * leaves sequence ids unchanged. In wrapped mode, only vertical scroll is
+ * provided, but it generates a change of "startres" which does require an
+ * update here.
+ */
@Override
public void propertyChange(PropertyChangeEvent evt)
{
- // Respond to viewport range changes (e.g. alignment panel was scrolled)
- // Both scrolling and resizing change viewport ranges: scrolling changes
- // both start and end points, but resize only changes end values.
- // Here we only want to fastpaint on a scroll, with resize using a normal
- // paint, so scroll events are identified as changes to the horizontal or
- // vertical start value.
- if (evt.getPropertyName().equals(ViewportRanges.STARTSEQ))
+ String propertyName = evt.getPropertyName();
+ if (propertyName.equals(ViewportRanges.STARTSEQ)
+ || (av.getWrapAlignment() && propertyName
+ .equals(ViewportRanges.STARTRES)))
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
*/
public void updateOverviewImage()
{
+ if (oviewCanvas == null)
+ {
+ /*
+ * panel has been disposed
+ */
+ return;
+ }
+
if ((getSize().width > 0) && (getSize().height > 0))
{
od.setWidth(getSize().width);
oviewCanvas.resetOviewDims(od);
updateOverviewImage();
}
+
+ /**
+ * Removes this object as a property change listener, and nulls references
+ */
+ protected void dispose()
+ {
+ try
+ {
+ av.getRanges().removePropertyChangeListener(this);
+ } finally
+ {
+ av = null;
+ oviewCanvas = null;
+ ap = null;
+ od = null;
+ }
+ }
}
sg.setStartRes(min);
sg.setEndRes(max);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(false);
av.sendSelection();
}
av.showColumn(reveal[0]);
reveal = null;
ap.paintAlignment(true);
- if (ap.overviewPanel != null)
- {
- ap.overviewPanel.updateOverviewImage();
- }
av.sendSelection();
}
});
av.showAllHiddenColumns();
reveal = null;
ap.paintAlignment(true);
- if (ap.overviewPanel != null)
- {
- ap.overviewPanel.updateOverviewImage();
- }
av.sendSelection();
}
});
}
ap.paintAlignment(true);
- if (ap.overviewPanel != null)
- {
- ap.overviewPanel.updateOverviewImage();
- }
av.sendSelection();
}
});
@Override
public void paint(Graphics g)
{
- drawScale(g, av.getRanges().getStartRes(), av.getRanges().getEndRes(),
- getSize().width,
- getSize().height);
+ /*
+ * shouldn't get called in wrapped mode as the scale above is
+ * drawn instead by SeqCanvas.drawNorthScale
+ */
+ if (!av.getWrapAlignment())
+ {
+ drawScale(g, av.getRanges().getStartRes(),
+ av.getRanges().getEndRes(), getSize().width, getSize().height);
+ }
}
// scalewidth will normally be screenwidth,
FontMetrics fm = getFontMetrics(av.getFont());
+ LABEL_EAST = 0;
+ LABEL_WEST = 0;
+
if (av.getScaleRightWrapped())
{
LABEL_EAST = fm.stringWidth(getMask());
av.setWrappedWidth(cWidth);
- av.getRanges().setEndRes(av.getRanges().getStartRes() + cWidth - 1);
+ av.getRanges().setViewportStartAndWidth(startRes, cWidth);
int endx;
int ypos = hgap;
- int maxwidth = av.getAlignment().getWidth() - 1;
+ int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
+ .findColumnPosition(maxwidth);
}
while ((ypos <= canvasHeight) && (startRes < maxwidth))
int res = 0;
int x = evt.getX();
+ int startRes = av.getRanges().getStartRes();
if (av.getWrapAlignment())
{
int y = evt.getY();
y -= hgap;
- x -= seqCanvas.LABEL_WEST;
+ x = Math.max(0, x - seqCanvas.LABEL_WEST);
int cwidth = seqCanvas.getWrappedCanvasWidth(getSize().width);
if (cwidth < 1)
}
wrappedBlock = y / cHeight;
- wrappedBlock += av.getRanges().getStartRes() / cwidth;
-
- res = wrappedBlock * cwidth + x / av.getCharWidth();
-
+ wrappedBlock += startRes / cwidth;
+ int startOffset = startRes % cwidth; // in case start is scrolled right
+ // from 0
+ res = wrappedBlock * cwidth
+ + Math.min(cwidth - 1, startOffset + x / av.getCharWidth());
}
else
{
- res = (x / av.getCharWidth()) + av.getRanges().getStartRes();
+ res = (x / av.getCharWidth()) + startRes;
}
if (av.hasHiddenColumns())
int absAlignmentIndex = alignment.findIndex(sequence);
int alignmentIndex = adjustForHiddenSeqs(absAlignmentIndex);
- if (hiddenSequences[alignmentIndex] != null)
+ if (alignmentIndex < 0 || hiddenSequences[alignmentIndex] != null)
{
System.out.println("ERROR!!!!!!!!!!!");
+ return;
}
hiddenSequences[alignmentIndex] = sequence;
}
/**
- * Convert absolute alignment index to visible alignment index
+ * Convert absolute alignment index to visible alignment index (or -1 if
+ * before the first visible sequence)
*
* @param alignmentIndex
* @return
break;
}
case KeyEvent.VK_PAGE_UP:
- if (viewport.getWrapAlignment())
- {
- vpRanges.scrollUp(true);
- }
- else
- {
- vpRanges.pageUp();
- }
+ vpRanges.pageUp();
break;
case KeyEvent.VK_PAGE_DOWN:
- if (viewport.getWrapAlignment())
- {
- vpRanges.scrollUp(false);
- }
- else
- {
- vpRanges.pageDown();
- }
+ vpRanges.pageDown();
break;
}
}
{
viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
alignPanel.paintAlignment(true);
- if (alignPanel.getOverviewPanel() != null)
- {
- alignPanel.getOverviewPanel().updateOverviewImage();
- }
}
/**
}
JInternalFrame frame = new JInternalFrame();
- OverviewPanel overview = new OverviewPanel(alignPanel);
+ final OverviewPanel overview = new OverviewPanel(alignPanel);
frame.setContentPane(overview);
Desktop.addInternalFrame(frame, MessageManager.formatMessage(
"label.overview_params", new Object[] { this.getTitle() }),
public void internalFrameClosed(
javax.swing.event.InternalFrameEvent evt)
{
+ overview.dispose();
alignPanel.setOverviewPanel(null);
};
});
annotationSpaceFillerHolder.setVisible(true);
}
- if (wrap)
- {
- int widthInRes = getSeqPanel().seqCanvas
- .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
- vpRanges.setViewportWidth(widthInRes);
- }
- else
- {
- int widthInRes = (getSeqPanel().seqCanvas.getWidth() / av
- .getCharWidth()) - 1;
- int heightInSeq = (getSeqPanel().seqCanvas.getHeight() / av
- .getCharHeight()) - 1;
+ int canvasWidth = getSeqPanel().seqCanvas.getWidth();
+ if (canvasWidth > 0)
+ { // may not yet be laid out
+ if (wrap)
+ {
+ int widthInRes = getSeqPanel().seqCanvas
+ .getWrappedCanvasWidth(canvasWidth);
+ vpRanges.setViewportWidth(widthInRes);
+ }
+ else
+ {
+ int widthInRes = (canvasWidth / av.getCharWidth()) - 1;
+ int heightInSeq = (getSeqPanel().seqCanvas.getHeight() / av
+ .getCharHeight()) - 1;
- vpRanges.setViewportWidth(widthInRes);
- vpRanges.setViewportHeight(heightInSeq);
+ vpRanges.setViewportWidth(widthInRes);
+ vpRanges.setViewportHeight(heightInSeq);
+ }
}
idSpaceFillerPanel1.setVisible(!wrap);
@Override
public void adjustmentValueChanged(AdjustmentEvent evt)
{
- int oldX = vpRanges.getStartRes();
- int oldwidth = vpRanges.getViewportWidth();
- int oldY = vpRanges.getStartSeq();
- int oldheight = vpRanges.getViewportHeight();
-
if (av.getWrapAlignment())
{
- if (evt.getSource() == hscroll)
- {
- return; // no horizontal scroll when wrapped
- }
- else if (evt.getSource() == vscroll)
+ adjustScrollingWrapped(evt);
+ return;
+ }
+
+ if (evt.getSource() == hscroll)
+ {
+ int oldX = vpRanges.getStartRes();
+ int oldwidth = vpRanges.getViewportWidth();
+ int x = hscroll.getValue();
+ int width = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
+
+ // if we're scrolling to the position we're already at, stop
+ // this prevents infinite recursion of events when the scroll/viewport
+ // ranges values are the same
+ if ((x == oldX) && (width == oldwidth))
{
- int offy = vscroll.getValue();
- int rowSize = getSeqPanel().seqCanvas
- .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
-
- // if we're scrolling to the position we're already at, stop
- // this prevents infinite recursion of events when the scroll/viewport
- // ranges values are the same
- if ((offy * rowSize == oldX) && (oldwidth == rowSize))
- {
- return;
- }
- else if (offy > -1)
- {
- vpRanges.setViewportStartAndWidth(offy * rowSize, rowSize);
- }
+ return;
}
- else
+ vpRanges.setViewportStartAndWidth(x, width);
+ }
+ else if (evt.getSource() == vscroll)
+ {
+ int oldY = vpRanges.getStartSeq();
+ int oldheight = vpRanges.getViewportHeight();
+ int y = vscroll.getValue();
+ int height = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight();
+
+ // if we're scrolling to the position we're already at, stop
+ // this prevents infinite recursion of events when the scroll/viewport
+ // ranges values are the same
+ if ((y == oldY) && (height == oldheight))
{
- // This is only called if file loaded is a jar file that
- // was wrapped when saved and user has wrap alignment true
- // as preference setting
- SwingUtilities.invokeLater(new Runnable()
- {
- @Override
- public void run()
- {
- // When updating scrolling to use ViewportChange events, this code
- // could not be validated and it is not clear if it is now being
- // called. Log warning here in case it is called and unforeseen
- // problems occur
- Cache.log
- .warn("Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences");
-
- // scroll to start of panel
- vpRanges.setStartRes(0);
- vpRanges.setStartSeq(0);
- }
- });
+ return;
}
+ vpRanges.setViewportStartAndHeight(y, height);
+ }
+ if (!fastPaint)
+ {
repaint();
}
- else
+ }
+
+ /**
+ * Responds to a scroll change by setting the start position of the viewport.
+ * Does
+ *
+ * @param evt
+ */
+ protected void adjustScrollingWrapped(AdjustmentEvent evt)
+ {
+ if (evt.getSource() == hscroll)
{
- // horizontal scroll
- if (evt.getSource() == hscroll)
- {
- int x = hscroll.getValue();
- int width = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
+ return; // no horizontal scroll when wrapped
+ }
+ if (evt.getSource() == vscroll)
+ {
+ int newY = vscroll.getValue();
- // if we're scrolling to the position we're already at, stop
- // this prevents infinite recursion of events when the scroll/viewport
- // ranges values are the same
- if ((x == oldX) && (width == oldwidth))
- {
- return;
- }
- vpRanges.setViewportStartAndWidth(x, width);
- }
- else if (evt.getSource() == vscroll)
+ /*
+ * if we're scrolling to the position we're already at, stop
+ * this prevents infinite recursion of events when the scroll/viewport
+ * ranges values are the same
+ */
+ int oldX = vpRanges.getStartRes();
+ int oldY = vpRanges.getWrappedScrollPosition(oldX);
+ if (oldY == newY)
{
- int y = vscroll.getValue();
- int height = getSeqPanel().seqCanvas.getHeight()
- / av.getCharHeight();
-
- // if we're scrolling to the position we're already at, stop
- // this prevents infinite recursion of events when the scroll/viewport
- // ranges values are the same
- if ((y == oldY) && (height == oldheight))
- {
- return;
- }
- vpRanges.setViewportStartAndHeight(y, height);
+ return;
}
- if (!fastPaint)
+ if (newY > -1)
{
- repaint();
+ /*
+ * limit page up/down to one width's worth of positions
+ */
+ int rowSize = vpRanges.getViewportWidth();
+ int newX = newY > oldY ? oldX + rowSize : oldX - rowSize;
+ vpRanges.setViewportStartAndWidth(Math.max(0, newX), rowSize);
}
}
+ else
+ {
+ // This is only called if file loaded is a jar file that
+ // was wrapped when saved and user has wrap alignment true
+ // as preference setting
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ // When updating scrolling to use ViewportChange events, this code
+ // could not be validated and it is not clear if it is now being
+ // called. Log warning here in case it is called and unforeseen
+ // problems occur
+ Cache.log
+ .warn("Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences");
+
+ // scroll to start of panel
+ vpRanges.setStartRes(0);
+ vpRanges.setStartSeq(0);
+ }
+ });
+ }
+ repaint();
}
/**
setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq());
}
- /*
- * Set vertical scroll bar parameters for wrapped panel
- * @param res
- * the residue to scroll to
+ /**
+ * Set vertical scroll bar position, and number of increments, for wrapped
+ * panel
+ *
+ * @param topLeftColumn
+ * the column position at top left (0..)
*/
- private void setScrollingForWrappedPanel(int res)
+ private void setScrollingForWrappedPanel(int topLeftColumn)
{
- // get the width of the alignment in residues
- int maxwidth = av.getAlignment().getWidth();
- if (av.hasHiddenColumns())
- {
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
- }
+ int scrollPosition = vpRanges.getWrappedScrollPosition(topLeftColumn);
+ int maxScroll = vpRanges.getWrappedMaxScroll(topLeftColumn);
- // get the width of the canvas in residues
- int canvasWidth = getSeqPanel().seqCanvas
- .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
- if (canvasWidth > 0)
- {
- // position we want to scroll to is number of canvasWidth's to get there
- int current = res / canvasWidth;
-
- // max scroll position: add one because extent is 1 and scrollbar value
- // can only be set to at most max - extent
- int max = maxwidth / canvasWidth + 1;
- vscroll.setUnitIncrement(1);
- vscroll.setValues(current, 1, 0, max);
- }
+ /*
+ * a scrollbar's value can be set to at most (maximum-extent)
+ * so we add extent (1) to the maxScroll value
+ */
+ vscroll.setUnitIncrement(1);
+ vscroll.setValues(scrollPosition, 1, 0, maxScroll + 1);
}
/**
// initialise threshold slider and selector
threshold.setSelectedIndex(cs.isAboveThreshold() ? 1 : 2);
slider.setEnabled(true);
+ slider.setValue((int) (cs.getThreshold() * scaleFactor));
thresholdValue.setEnabled(true);
threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
-
+ threshline.value = cs.getThreshold();
}
adjusting = false;
*/
public void fastPaint(int vertical)
{
- if (gg == null)
+ /*
+ * for now, not attempting fast paint of wrapped ids...
+ */
+ if (gg == null || av.getWrapAlignment())
{
repaint();
Color currentColor = Color.white;
Color currentTextColor = Color.black;
- final boolean doHiddenCheck = av.isDisplayReferenceSeq()
- || av.hasHiddenRows(), hiddenRows = av.hasHiddenRows();
+ boolean hasHiddenRows = av.hasHiddenRows();
if (av.getWrapAlignment())
{
- int maxwidth = av.getAlignment().getWidth();
- int alheight = av.getAlignment().getHeight();
+ drawIdsWrapped(starty, hasHiddenRows);
+ return;
+ }
- if (av.hasHiddenColumns())
- {
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
- }
+ // No need to hang on to labels if we're not wrapped
+ labels = null;
- int annotationHeight = 0;
+ // Now draw the id strings
+ int panelWidth = getWidth();
+ int xPos = 0;
+
+ SequenceI sequence;
+ // Now draw the id strings
+ for (int i = starty; i <= endy; i++)
+ {
+ sequence = av.getAlignment().getSequenceAt(i);
- if (av.isShowAnnotation())
+ if (sequence == null)
{
- if (ap == null)
- {
- ap = new AnnotationPanel(av);
- }
+ continue;
+ }
- annotationHeight = ap.adjustPanelHeight();
- if (labels == null)
- {
- labels = new AnnotationLabels(av);
- }
+ if (hasHiddenRows || av.isDisplayReferenceSeq())
+ {
+ setHiddenFont(sequence);
}
- int hgap = av.getCharHeight();
- if (av.getScaleAboveWrapped())
+ // Selected sequence colours
+ if ((searchResults != null) && searchResults.contains(sequence))
{
- hgap += av.getCharHeight();
+ currentColor = Color.black;
+ currentTextColor = Color.white;
}
+ else if ((av.getSelectionGroup() != null)
+ && av.getSelectionGroup().getSequences(null)
+ .contains(sequence))
+ {
+ currentColor = Color.lightGray;
+ currentTextColor = Color.black;
+ }
+ else
+ {
+ currentColor = av.getSequenceColour(sequence);
+ currentTextColor = Color.black;
+ }
+
+ gg.setColor(currentColor);
+
+ gg.fillRect(0, (i - starty) * av.getCharHeight(), getWidth(),
+ av.getCharHeight());
- int cHeight = alheight * av.getCharHeight() + hgap + annotationHeight;
+ gg.setColor(currentTextColor);
- int rowSize = av.getRanges().getEndRes()
- - av.getRanges().getStartRes();
+ String string = sequence.getDisplayId(av.getShowJVSuffix());
- // Draw the rest of the panels
- for (int ypos = hgap, row = av.getRanges().getStartRes(); (ypos <= getHeight())
- && (row < maxwidth); ypos += cHeight, row += rowSize)
+ if (av.isRightAlignIds())
{
- for (int i = starty; i < alheight; i++)
- {
- SequenceI s = av.getAlignment().getSequenceAt(i);
- if (doHiddenCheck)
- {
- setHiddenFont(s);
- }
- else
- {
- gg.setFont(getIdfont());
- }
-
- drawIdString(gg, hiddenRows, s, i, 0, ypos);
- }
+ xPos = panelWidth - fm.stringWidth(string) - 4;
+ }
- if (labels != null && av.isShowAnnotation())
- {
- gg.translate(0, ypos + (alheight * av.getCharHeight()));
- labels.drawComponent(gg, getWidth());
- gg.translate(0, -ypos - (alheight * av.getCharHeight()));
- }
+ gg.drawString(string, xPos,
+ (((i - starty) * av.getCharHeight()) + av.getCharHeight())
+ - (av.getCharHeight() / 5));
+
+ if (hasHiddenRows)
+ {
+ drawMarker(i, starty, 0);
}
}
- else
- {
- // No need to hang on to labels if we're not wrapped
- labels = null;
+ }
- // Now draw the id strings
- int panelWidth = getWidth();
- int xPos = 0;
+ /**
+ * Draws sequence ids in wrapped mode
+ *
+ * @param starty
+ * @param hasHiddenRows
+ */
+ protected void drawIdsWrapped(int starty, boolean hasHiddenRows)
+ {
+ int maxwidth = av.getAlignment().getWidth();
+ int alheight = av.getAlignment().getHeight();
- SequenceI sequence;
- // Now draw the id strings
- for (int i = starty; i <= endy; i++)
- {
- sequence = av.getAlignment().getSequenceAt(i);
+ if (av.hasHiddenColumns())
+ {
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
+ }
- if (sequence == null)
- {
- continue;
- }
+ int annotationHeight = 0;
- if (doHiddenCheck)
- {
- setHiddenFont(sequence);
- }
+ if (av.isShowAnnotation())
+ {
+ if (ap == null)
+ {
+ ap = new AnnotationPanel(av);
+ }
- // Selected sequence colours
- if ((searchResults != null) && searchResults.contains(sequence))
- {
- currentColor = Color.black;
- currentTextColor = Color.white;
- }
- else if ((av.getSelectionGroup() != null)
- && av.getSelectionGroup().getSequences(null)
- .contains(sequence))
- {
- currentColor = Color.lightGray;
- currentTextColor = Color.black;
- }
- else
- {
- currentColor = av.getSequenceColour(sequence);
- currentTextColor = Color.black;
- }
+ annotationHeight = ap.adjustPanelHeight();
+ if (labels == null)
+ {
+ labels = new AnnotationLabels(av);
+ }
+ }
- gg.setColor(currentColor);
+ int hgap = av.getCharHeight();
+ if (av.getScaleAboveWrapped())
+ {
+ hgap += av.getCharHeight();
+ }
- gg.fillRect(0, (i - starty) * av.getCharHeight(), getWidth(),
- av.getCharHeight());
+ int cHeight = alheight * av.getCharHeight() + hgap + annotationHeight;
- gg.setColor(currentTextColor);
+ ViewportRanges ranges = av.getRanges();
- String string = sequence.getDisplayId(av.getShowJVSuffix());
+ int rowSize = ranges.getViewportWidth();
- if (av.isRightAlignIds())
+ /*
+ * draw repeating sequence ids until out of sequence data or
+ * out of visible space, whichever comes first
+ */
+ int ypos = hgap;
+ int row = ranges.getStartRes();
+ while ((ypos <= getHeight()) && (row < maxwidth))
+ {
+ for (int i = starty; i < alheight; i++)
+ {
+ SequenceI s = av.getAlignment().getSequenceAt(i);
+ if (hasHiddenRows || av.isDisplayReferenceSeq())
{
- xPos = panelWidth - fm.stringWidth(string) - 4;
+ setHiddenFont(s);
}
-
- gg.drawString(string, xPos,
- (((i - starty) * av.getCharHeight()) + av.getCharHeight())
- - (av.getCharHeight() / 5));
-
- if (hiddenRows)
+ else
{
- drawMarker(i, starty, 0);
+ gg.setFont(getIdfont());
}
+ drawIdString(gg, hasHiddenRows, s, i, 0, ypos);
+ }
+
+ if (labels != null && av.isShowAnnotation())
+ {
+ gg.translate(0, ypos + (alheight * av.getCharHeight()));
+ labels.drawComponent(gg, getWidth());
+ gg.translate(0, -ypos - (alheight * av.getCharHeight()));
}
+ ypos += cHeight;
+ row += rowSize;
}
}
this.idfont = idfont;
}
+ /**
+ * Respond to viewport range changes (e.g. alignment panel was scrolled). Both
+ * scrolling and resizing change viewport ranges. Scrolling changes both start
+ * and end points, but resize only changes end values. Here we only want to
+ * fastpaint on a scroll, with resize using a normal paint, so scroll events
+ * are identified as changes to the horizontal or vertical start value.
+ * <p>
+ * In unwrapped mode, only responds to a vertical scroll, as horizontal scroll
+ * leaves sequence ids unchanged. In wrapped mode, only vertical scroll is
+ * provided, but it generates a change of "startres" which does require an
+ * update here.
+ */
@Override
public void propertyChange(PropertyChangeEvent evt)
{
- // Respond to viewport range changes (e.g. alignment panel was scrolled)
- // Both scrolling and resizing change viewport ranges: scrolling changes
- // both start and end points, but resize only changes end values.
- // Here we only want to fastpaint on a scroll, with resize using a normal
- // paint, so scroll events are identified as changes to the horizontal or
- // vertical start value.
- if (evt.getPropertyName().equals(ViewportRanges.STARTSEQ))
+ String propertyName = evt.getPropertyName();
+ if (propertyName.equals(ViewportRanges.STARTSEQ)
+ || (av.getWrapAlignment() && propertyName
+ .equals(ViewportRanges.STARTRES)))
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
}
lastid = seq;
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false);
}
/**
av.isSelectionGroupChanged(true);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false);
}
/**
@Override
public void mouseDragged(MouseEvent evt)
{
- if (!SwingUtilities.isRightMouseButton(evt)
- && !av.getWrapAlignment())
+ if (!SwingUtilities.isRightMouseButton(evt))
{
od.updateViewportFromMouse(evt.getX(), evt.getY(), av
.getAlignment().getHiddenSequences(), av.getAlignment()
.getHiddenColumns());
-
}
}
});
showPopupMenu(evt);
}
}
- else if (!av.getWrapAlignment())
+ else
+ // if (!av.getWrapAlignment())
{
od.updateViewportFromMouse(evt.getX(), evt.getY(), av
.getAlignment().getHiddenSequences(), av.getAlignment()
}
});
-
updateOverviewImage();
}
*/
public void updateOverviewImage()
{
+ if (oviewCanvas == null)
+ {
+ /*
+ * panel has been disposed
+ */
+ return;
+ }
+
if ((getWidth() > 0) && (getHeight() > 0))
{
od.setWidth(getWidth());
Thread thread = new Thread(this);
thread.start();
repaint();
-
}
@Override
{
setBoxPosition();
}
+
+ /**
+ * Removes this object as a property change listener, and nulls references
+ */
+ protected void dispose()
+ {
+ try
+ {
+ av.getRanges().removePropertyChangeListener(this);
+ } finally
+ {
+ av = null;
+ oviewCanvas = null;
+ ap = null;
+ od = null;
+ }
+ }
}
av.showColumn(reveal[0]);
reveal = null;
ap.paintAlignment(true);
- if (ap.overviewPanel != null)
- {
- ap.overviewPanel.updateOverviewImage();
- }
av.sendSelection();
}
});
av.showAllHiddenColumns();
reveal = null;
ap.paintAlignment(true);
- if (ap.overviewPanel != null)
- {
- ap.overviewPanel.updateOverviewImage();
- }
av.sendSelection();
}
});
}
ap.paintAlignment(true);
- if (ap.overviewPanel != null)
- {
- ap.overviewPanel.updateOverviewImage();
- }
av.sendSelection();
}
});
@Override
public void paintComponent(Graphics g)
{
- drawScale(g, av.getRanges().getStartRes(), av.getRanges().getEndRes(),
- getWidth(), getHeight());
+ /*
+ * shouldn't get called in wrapped mode as the scale above is
+ * drawn instead by SeqCanvas.drawNorthScale
+ */
+ if (!av.getWrapAlignment())
+ {
+ drawScale(g, av.getRanges().getStartRes(),
+ av.getRanges().getEndRes(), getWidth(), getHeight());
+ }
}
// scalewidth will normally be screenwidth,
FontMetrics fm = getFontMetrics(av.getFont());
+ LABEL_EAST = 0;
+ LABEL_WEST = 0;
+
if (av.getScaleRightWrapped())
{
LABEL_EAST = fm.stringWidth(getMask());
av.setWrappedWidth(cWidth);
- av.getRanges().setEndRes(av.getRanges().getStartRes() + cWidth - 1);
+ av.getRanges().setViewportStartAndWidth(startRes, cWidth);
int endx;
int ypos = hgap;
- int maxwidth = av.getAlignment().getWidth() - 1;
+ int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
+ .findColumnPosition(maxwidth);
}
while ((ypos <= canvasHeight) && (startRes < maxwidth))
{
String eventName = evt.getPropertyName();
- if (!av.getWrapAlignment())
+ if (av.getWrapAlignment())
+ {
+ if (eventName.equals(ViewportRanges.STARTRES))
+ {
+ repaint();
+ }
+ }
+ else
{
int scrollX = 0;
if (eventName.equals(ViewportRanges.STARTRES))
int res = 0;
int x = evt.getX();
+ int startRes = av.getRanges().getStartRes();
if (av.getWrapAlignment())
{
int y = evt.getY();
y -= hgap;
- x -= seqCanvas.LABEL_WEST;
+ x = Math.max(0, x - seqCanvas.LABEL_WEST);
int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
if (cwidth < 1)
}
wrappedBlock = y / cHeight;
- wrappedBlock += av.getRanges().getStartRes() / cwidth;
-
- res = wrappedBlock * cwidth + x / av.getCharWidth();
-
+ wrappedBlock += startRes / cwidth;
+ // allow for wrapped view scrolled right (possible from Overview)
+ int startOffset = startRes % cwidth;
+ res = wrappedBlock * cwidth
+ + Math.min(cwidth - 1, startOffset + x / av.getCharWidth());
}
else
{
// right-hand gutter
x = seqCanvas.getX() + seqCanvas.getWidth();
}
- res = (x / av.getCharWidth()) + av.getRanges().getStartRes();
+ res = (x / av.getCharWidth()) + startRes;
if (res > av.getRanges().getEndRes())
{
// moused off right
}
Color featureColour = getColour(sequenceFeature);
+ if (featureColour == null)
+ {
+ // score feature outwith threshold for colouring
+ continue;
+ }
+
boolean isContactFeature = sequenceFeature.isContactFeature();
if (isContactFeature)
drawnColour = featureColour;
}
}
- else if (showFeature(sequenceFeature))
+ else
{
if (av.isShowSequenceFeaturesHeight()
&& !Float.isNaN(sequenceFeature.score))
public void setWrapAlignment(boolean state)
{
viewStyle.setWrapAlignment(state);
+ ranges.setWrappedMode(state);
}
/**
// common hide/show seq stuff
public void showAllHiddenSeqs()
{
+ int startSeq = ranges.getStartSeq();
+ int endSeq = ranges.getEndSeq();
+
if (alignment.getHiddenSequences().getSize() > 0)
{
if (selectionGroup == null)
hiddenRepSequences = null;
+ ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
+
firePropertyChange("alignment", null, alignment.getSequences());
// used to set hasHiddenRows/hiddenRepSequences here, after the property
// changed event
public void showSequence(int index)
{
+ int startSeq = ranges.getStartSeq();
+ int endSeq = ranges.getEndSeq();
+
List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(
index, hiddenRepSequences);
if (tmp.size() > 0)
selectionGroup.addSequence(seq, false);
setSequenceAnnotationsVisible(seq, true);
}
+
+ ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
+
firePropertyChange("alignment", null, alignment.getSequences());
sendSelection();
}
public void hideSequence(SequenceI[] seq)
{
+ /*
+ * cache offset to first visible sequence
+ */
+ int startSeq = ranges.getStartSeq();
+
if (seq != null)
{
for (int i = 0; i < seq.length; i++)
alignment.getHiddenSequences().hideSequence(seq[i]);
setSequenceAnnotationsVisible(seq[i], false);
}
+ ranges.setStartSeq(startSeq);
firePropertyChange("alignment", null, alignment.getSequences());
}
}
resetAlignmentDims();
// boxX, boxY is the x,y location equivalent to startRes, startSeq
- boxX = Math.round((float) startRes * width / alwidth);
+ int xPos = Math.min(startRes, alwidth - vpwidth + 1);
+ boxX = Math.round((float) xPos * width / alwidth);
boxY = Math.round((float) startSeq * sequencesHeight / alheight);
// boxWidth is the width in residues translated to pixels
y = 0;
}
+ if (ranges.isWrappedMode())
+ {
+ y = 0; // sorry, no vertical scroll when wrapped
+ }
+
//
// Convert x value to residue position
//
y = 0;
}
+ if (ranges.isWrappedMode())
+ {
+ y = 0; // sorry, no vertical scroll when wrapped
+ }
+
//
// Convert x value to residue position
//
// so convert back after getting visible region position
yAsSeq = hiddenSeqs.adjustForHiddenSeqs(hiddenSeqs
.findIndexWithoutHiddenSeqs(yAsSeq));
+ yAsSeq = Math.max(yAsSeq, 0); // -1 if before first visible sequence
// check in case we went off the edge of the alignment
int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
int visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
+ visYAsSeq = Math.max(visYAsSeq, 0); // -1 if before first visible sequence
if (visYAsSeq + vpheight - 1 > visAlignHeight)
{
// went past the end of the alignment, adjust backwards
// update viewport
ranges.setStartRes(visXAsRes);
ranges.setStartSeq(visYAsSeq);
-
}
/**
public static final String ENDSEQ = "endseq";
+ private boolean wrappedMode = false;
+
// start residue of viewport
private int startRes;
public void setStartEndRes(int start, int end)
{
int oldstartres = this.startRes;
- if (start > getVisibleAlignmentWidth() - 1)
+
+ /*
+ * if not wrapped, don't leave white space at the right margin
+ */
+ int lastColumn = getVisibleAlignmentWidth() - 1;
+ if (!wrappedMode && (start > lastColumn))
{
- startRes = Math.max(getVisibleAlignmentWidth() - 1, 0);
+ startRes = Math.max(lastColumn, 0);
}
else if (start < 0)
{
{
endRes = 0;
}
- else if (end > getVisibleAlignmentWidth() - 1)
+ else if (!wrappedMode && (end > lastColumn))
{
- endRes = Math.max(getVisibleAlignmentWidth() - 1, 0);
+ endRes = Math.max(lastColumn, 0);
}
else
{
}
/**
- * Set last residue visible in the viewport. Fires a property change event.
- *
- * @param res
- * residue position
- */
- public void setEndRes(int res)
- {
- int startres = res;
- int width = getViewportWidth();
- if (startres + width - 1 > getVisibleAlignmentWidth() - 1)
- {
- startres = getVisibleAlignmentWidth() - width;
- }
- setStartEndRes(startres - width + 1, startres);
- }
-
- /**
* Set the first sequence visible in the viewport, maintaining the height. If
* the viewport would extend past the last sequence, sets the viewport so it
* sits at the bottom of the alignment. Fires a property change event.
public void setStartEndSeq(int start, int end)
{
int oldstartseq = this.startSeq;
- if (start > getVisibleAlignmentHeight() - 1)
+ int visibleHeight = getVisibleAlignmentHeight();
+ if (start > visibleHeight - 1)
{
- startSeq = Math.max(getVisibleAlignmentHeight() - 1, 0);
+ startSeq = Math.max(visibleHeight - 1, 0);
}
else if (start < 0)
{
}
int oldendseq = this.endSeq;
- if (end >= getVisibleAlignmentHeight())
+ if (end >= visibleHeight)
{
- endSeq = Math.max(getVisibleAlignmentHeight() - 1, 0);
+ endSeq = Math.max(visibleHeight - 1, 0);
}
else if (end < 0)
{
{
vpstart = 0;
}
- else if ((w <= getVisibleAlignmentWidth())
- && (vpstart + w - 1 > getVisibleAlignmentWidth() - 1))
- // viewport width is less than the full alignment and we are running off the
- // RHS edge
+
+ /*
+ * if not wrapped, don't leave white space at the right margin
+ */
+ if (!wrappedMode)
{
- vpstart = getVisibleAlignmentWidth() - w;
+ if ((w <= getVisibleAlignmentWidth())
+ && (vpstart + w - 1 > getVisibleAlignmentWidth() - 1))
+ {
+ vpstart = getVisibleAlignmentWidth() - w;
+ }
+
}
setStartEndRes(vpstart, vpstart + w - 1);
}
*/
public void pageUp()
{
- setViewportStartAndHeight(2 * startSeq - endSeq, getViewportHeight());
+ if (wrappedMode)
+ {
+ setStartRes(Math.max(0, getStartRes() - getViewportWidth()));
+ }
+ else
+ {
+ setViewportStartAndHeight(startSeq - (endSeq - startSeq),
+ getViewportHeight());
+ }
}
/**
*/
public void pageDown()
{
- setViewportStartAndHeight(endSeq, getViewportHeight());
+ if (wrappedMode)
+ {
+ /*
+ * if height is more than width (i.e. not all sequences fit on screen),
+ * increase page down to height
+ */
+ int newStart = getStartRes()
+ + Math.max(getViewportHeight(), getViewportWidth());
+
+ /*
+ * don't page down beyond end of alignment, or if not all
+ * sequences fit in the visible height
+ */
+ if (newStart < getVisibleAlignmentWidth())
+ {
+ setStartRes(newStart);
+ }
+ }
+ else
+ {
+ setViewportStartAndHeight(endSeq, getViewportHeight());
+ }
+ }
+
+ public void setWrappedMode(boolean wrapped)
+ {
+ wrappedMode = wrapped;
+ }
+
+ public boolean isWrappedMode()
+ {
+ return wrappedMode;
+ }
+
+ /**
+ * Answers the vertical scroll position (0..) to set, given the visible column
+ * that is at top left.
+ *
+ * <pre>
+ * Example:
+ * viewport width 40 columns (0-39, 40-79, 80-119...)
+ * column 0 returns scroll position 0
+ * columns 1-40 return scroll position 1
+ * columns 41-80 return scroll position 2
+ * etc
+ * </pre>
+ *
+ * @param topLeftColumn
+ * (0..)
+ * @return
+ */
+ public int getWrappedScrollPosition(final int topLeftColumn)
+ {
+ int w = getViewportWidth();
+
+ /*
+ * visible whole widths
+ */
+ int scroll = topLeftColumn / w;
+
+ /*
+ * add 1 for a part width if there is one
+ */
+ scroll += topLeftColumn % w > 0 ? 1 : 0;
+
+ return scroll;
+ }
+
+ /**
+ * Answers the maximum wrapped vertical scroll value, given the column
+ * position (0..) to show at top left of the visible region.
+ *
+ * @param topLeftColumn
+ * @return
+ */
+ public int getWrappedMaxScroll(int topLeftColumn)
+ {
+ int scrollPosition = getWrappedScrollPosition(topLeftColumn);
+
+ /*
+ * how many more widths could be drawn after this one?
+ */
+ int columnsRemaining = getVisibleAlignmentWidth() - topLeftColumn;
+ int width = getViewportWidth();
+ int widthsRemaining = columnsRemaining / width
+ + (columnsRemaining % width > 0 ? 1 : 0) - 1;
+ int maxScroll = scrollPosition + widthsRemaining;
+
+ return maxScroll;
}
}
public Color getColour(SequenceFeature feature)
{
FeatureColourI fc = getFeatureStyle(feature.getType());
- return fc.getColor(feature);
+ return fc.isColored(feature) ? fc.getColor(feature) : null;
}
+ /**
+ * Answers true unless the feature has a score value which lies outside a
+ * minimum or maximum threshold configured for colouring. This method does not
+ * check feature type or group visibility.
+ *
+ * @param sequenceFeature
+ * @return
+ */
protected boolean showFeature(SequenceFeature sequenceFeature)
{
FeatureColourI fc = getFeatureStyle(sequenceFeature.type);
{
AlignmentI al = new Alignment(seqs);
HiddenSequences hs = al.getHiddenSequences();
- for (int i = 0; i < SEQ_COUNT; i++)
+ int height = al.getHeight();
+ for (int i = 0; i < height; i++)
{
assertEquals(i, hs.findIndexWithoutHiddenSeqs(i));
}
/*
* alignment is now seq0/2/3/4/7/8/9
*/
- assertEquals(SEQ_COUNT - 3, al.getHeight());
+ assertEquals(height - 3, al.getHeight());
assertEquals(0, hs.findIndexWithoutHiddenSeqs(0));
assertEquals(0, hs.findIndexWithoutHiddenSeqs(1));
assertEquals(1, hs.findIndexWithoutHiddenSeqs(2));
assertEquals(4, hs.findIndexWithoutHiddenSeqs(7));
assertEquals(5, hs.findIndexWithoutHiddenSeqs(8));
assertEquals(6, hs.findIndexWithoutHiddenSeqs(9));
+
+ /*
+ * hide first two sequences
+ */
+ hs.showAll(null);
+ hs.hideSequence(seqs[0]);
+ hs.hideSequence(seqs[1]);
+ assertEquals(-1, hs.findIndexWithoutHiddenSeqs(0));
+ assertEquals(-1, hs.findIndexWithoutHiddenSeqs(1));
+ for (int i = 2; i < height; i++)
+ {
+ assertEquals(i - 2, hs.findIndexWithoutHiddenSeqs(i));
+ }
}
/**
import jalview.schemes.PIDColourScheme;
import jalview.structure.StructureSelectionManager;
import jalview.util.MapList;
+import jalview.viewmodel.ViewportRanges;
import java.util.ArrayList;
import java.util.List;
SequenceI cons = testme.getConsensusSeq();
assertEquals("A-C", cons.getSequenceAsString());
}
+
+ @Test(groups = { "Functional" })
+ public void testHideRevealSequences()
+ {
+ ViewportRanges ranges = testee.getRanges();
+ assertEquals(3, al.getHeight());
+ assertEquals(0, ranges.getStartSeq());
+ assertEquals(2, ranges.getEndSeq());
+
+ /*
+ * hide first sequence
+ */
+ testee.hideSequence(new SequenceI[] { al.getSequenceAt(0) });
+ assertEquals(2, al.getHeight());
+ assertEquals(0, ranges.getStartSeq());
+ assertEquals(1, ranges.getEndSeq());
+
+ /*
+ * reveal hidden sequences above the first
+ */
+ testee.showSequence(0);
+ assertEquals(3, al.getHeight());
+ assertEquals(0, ranges.getStartSeq());
+ assertEquals(2, ranges.getEndSeq());
+
+ /*
+ * hide first and third sequences
+ */
+ testee.hideSequence(new SequenceI[] { al.getSequenceAt(0),
+ al.getSequenceAt(2) });
+ assertEquals(1, al.getHeight());
+ assertEquals(0, ranges.getStartSeq());
+ assertEquals(0, ranges.getEndSeq());
+
+ /*
+ * reveal all hidden sequences
+ */
+ testee.showAllHiddenSeqs();
+ assertEquals(3, al.getHeight());
+ assertEquals(0, ranges.getStartSeq());
+ assertEquals(2, ranges.getEndSeq());
+ }
}
FeatureColourFinder finder2 = new FeatureColourFinder(null);
assertTrue(finder2.noFeaturesDisplayed());
}
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_graduatedWithThreshold()
+ {
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
+ 2, 0f, "KdGroup"));
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4,
+ 4, 5f, "KdGroup"));
+ seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7,
+ 7, 10f, "KdGroup"));
+
+ /*
+ * graduated colour from 0 to 10
+ * above threshold value of 5
+ */
+ Color min = new Color(100, 50, 150);
+ Color max = new Color(200, 0, 100);
+ FeatureColourI fc = new FeatureColour(min, max, 0, 10);
+ fc.setAboveThreshold(true);
+ fc.setThreshold(5f);
+ fr.setColour("kd", fc);
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+
+ /*
+ * position 2, column 1, score 0 - below threshold - default colour
+ */
+ Color c = finder.findFeatureColour(Color.blue, seq, 1);
+ assertEquals(c, Color.blue);
+
+ /*
+ * position 4, column 3, score 5 - at threshold - default colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 3);
+ assertEquals(c, Color.blue);
+
+ /*
+ * position 7, column 9, score 10 - maximum colour in range
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 9);
+ assertEquals(c, max);
+
+ /*
+ * now colour below threshold of 5
+ */
+ fc.setBelowThreshold(true);
+
+ /*
+ * position 2, column 1, score 0 - min colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 1);
+ assertEquals(c, min);
+
+ /*
+ * position 4, column 3, score 5 - at threshold - default colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 3);
+ assertEquals(c, Color.blue);
+
+ /*
+ * position 7, column 9, score 10 - above threshold - default colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 9);
+ assertEquals(c, Color.blue);
+ }
}
import java.util.Arrays;
import java.util.List;
+import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
AlignmentI smallAl = gen.generate(7, 2, 2, 5, 5);
+ @BeforeClass(alwaysRun = true)
+ public void setUp()
+ {
+ gen = new AlignmentGenerator(false);
+ al = gen.generate(20, 30, 1, 5, 5);
+ smallAl = gen.generate(7, 2, 2, 5, 5);
+ }
+
@BeforeMethod(alwaysRun = true)
public void cleanUp()
{
}
@Test(groups = { "Functional" })
- public void testSetEndRes()
- {
- ViewportRanges vr = new ViewportRanges(al);
- vr.setEndRes(-1);
- assertEquals(vr.getEndRes(), 0);
-
- vr.setEndRes(al.getWidth() - 1);
- assertEquals(vr.getEndRes(), al.getWidth() - 1);
- }
-
- @Test(groups = { "Functional" })
public void testSetEndSeq()
{
ViewportRanges vr = new ViewportRanges(al);
vr.setEndSeq(al.getHeight());
assertEquals(vr.getEndSeq(), al.getHeight() - 1);
- vr.setEndRes(al.getHeight() - 1);
+ // vr.setEndRes(al.getHeight() - 1);
+ vr.setEndSeq(al.getHeight() - 1);
assertEquals(vr.getEndSeq(), al.getHeight() - 1);
}
assertTrue(l.verify(0, emptylist));
l.reset();
- vr.setEndRes(10);
- assertTrue(l.verify(1, Arrays.asList("startres")));
- l.reset();
-
- // no event fired for same value
- vr.setEndRes(10);
- assertTrue(l.verify(0, emptylist));
- l.reset();
-
vr.setStartSeq(4);
assertTrue(l.verify(1, Arrays.asList("startseq")));
l.reset();
assertTrue(l.verify(1, Arrays.asList("startres")));
l.reset();
}
+
+ @Test(groups = { "Functional" })
+ public void testGetWrappedScrollPosition()
+ {
+ AlignmentI al2 = gen.generate(157, 15, 1, 5, 5);
+ ViewportRanges vr = new ViewportRanges(al2);
+ vr.setStartEndRes(0, 39);
+ int width = vr.getViewportWidth(); // 40
+
+ /*
+ * scroll is 0 at column 0 (only)
+ */
+ assertEquals(vr.getWrappedScrollPosition(0), 0);
+
+ /*
+ * scroll is 1 at columns 1-40
+ */
+ int i = 1;
+ int j = width;
+ for (; i <= j; i++)
+ {
+ assertEquals(1, vr.getWrappedScrollPosition(i));
+ }
+
+ /*
+ * scroll is 2 at columns 41-80, etc
+ */
+ j += width;
+ for (; i <= j; i++)
+ {
+ assertEquals(2, vr.getWrappedScrollPosition(i), "For " + i);
+ }
+ }
+
+ @Test(groups = { "Functional" })
+ public void testPageUpDownWrapped()
+ {
+ /*
+ * 15 sequences, 110 residues wide (+gaps)
+ */
+ AlignmentI al2 = gen.generate(110, 15, 1, 5, 5);
+
+ ViewportRanges vr = new ViewportRanges(al2);
+ vr.setWrappedMode(true);
+
+ // first row
+ vr.setViewportStartAndWidth(0, 40);
+ int width = vr.getViewportWidth();
+ assertEquals(width, 40);
+ assertEquals(vr.getStartRes(), 0);
+ assertEquals(vr.getEndRes(), 39);
+ assertEquals(vr.getStartSeq(), 0);
+ assertEquals(vr.getEndSeq(), 14);
+
+ // second row
+ vr.pageDown();
+ assertEquals(vr.getStartRes(), 40);
+ assertEquals(vr.getEndRes(), 79);
+ assertEquals(vr.getStartSeq(), 0);
+ assertEquals(vr.getEndSeq(), 14);
+
+ // third and last row
+ // note endRes is nominal (>width) to preserve viewport width
+ vr.pageDown();
+ assertEquals(vr.getStartRes(), 80);
+ assertEquals(vr.getEndRes(), 119);
+ assertEquals(vr.getStartSeq(), 0);
+ assertEquals(vr.getEndSeq(), 14);
+
+ // another pageDown should do nothing
+ vr.pageDown();
+ assertEquals(vr.getStartRes(), 80);
+ assertEquals(vr.getEndRes(), 119);
+ assertEquals(vr.getStartSeq(), 0);
+ assertEquals(vr.getEndSeq(), 14);
+
+ // back to second row
+ vr.pageUp();
+ assertEquals(vr.getStartRes(), 40);
+ assertEquals(vr.getEndRes(), 79);
+ assertEquals(vr.getStartSeq(), 0);
+ assertEquals(vr.getEndSeq(), 14);
+
+ // back to first row
+ vr.pageUp();
+ assertEquals(vr.getStartRes(), 0);
+ assertEquals(vr.getEndRes(), 39);
+ assertEquals(vr.getStartSeq(), 0);
+ assertEquals(vr.getEndSeq(), 14);
+
+ // another pageUp should do nothing
+ vr.pageUp();
+ assertEquals(vr.getStartRes(), 0);
+ assertEquals(vr.getEndRes(), 39);
+ assertEquals(vr.getStartSeq(), 0);
+ assertEquals(vr.getEndSeq(), 14);
+
+ /*
+ * simulate scroll right a few positions
+ */
+ vr.setStartRes(5);
+ assertEquals(vr.getStartRes(), 5);
+ assertEquals(vr.getEndRes(), 5 + width - 1); // 44
+
+ vr.pageDown(); // 5-44 shifts to 45-84
+ assertEquals(vr.getStartRes(), 45);
+ assertEquals(vr.getEndRes(), 84);
+
+ vr.pageDown(); // 45-84 shifts to 85-124
+ assertEquals(vr.getStartRes(), 85);
+ assertEquals(vr.getEndRes(), 124);
+
+ vr.pageDown(); // no change - at end already
+ assertEquals(vr.getStartRes(), 85);
+ assertEquals(vr.getEndRes(), 124);
+
+ vr.pageUp(); // back we go
+ assertEquals(vr.getStartRes(), 45);
+ assertEquals(vr.getEndRes(), 84);
+
+ vr.pageUp();
+ assertEquals(vr.getStartRes(), 5);
+ assertEquals(vr.getEndRes(), 44);
+
+ vr.pageUp(); // back to the start
+ assertEquals(vr.getStartRes(), 0);
+ assertEquals(vr.getEndRes(), 39);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testSetStartEndResWrapped()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+ vr.setWrappedMode(true);
+ vr.setStartEndRes(-1, -1);
+ assertEquals(vr.getStartRes(), 0);
+ assertEquals(vr.getEndRes(), 0);
+
+ vr.setStartEndRes(5, 19);
+ assertEquals(vr.getStartRes(), 5);
+ assertEquals(vr.getEndRes(), 19);
+
+ // bounds are not constrained to alignment width
+ // when in wrapped mode
+ vr.setStartEndRes(88, 888);
+ assertEquals(vr.getStartRes(), 88);
+ assertEquals(vr.getEndRes(), 888);
+
+ ViewportRanges vrsmall = new ViewportRanges(smallAl);
+ vrsmall.setWrappedMode(true);
+ vrsmall.setStartEndRes(88, 888);
+ assertEquals(vrsmall.getStartRes(), 88);
+ assertEquals(vrsmall.getEndRes(), 888);
+
+ // make visible alignment width = 0
+ smallAl.getHiddenColumns().hideColumns(0, 6);
+ vrsmall.setStartEndRes(0, 4);
+ assertEquals(vrsmall.getStartRes(), 0);
+ assertEquals(vrsmall.getEndRes(), 4);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testSetViewportStartAndWidthWrapped()
+ {
+ ViewportRanges vr = new ViewportRanges(al);
+ vr.setWrappedMode(true);
+ vr.setViewportStartAndWidth(2, 6);
+ assertEquals(vr.getViewportWidth(), 6);
+ assertEquals(vr.getStartRes(), 2);
+
+ // reset -ve values of start to 0
+ vr.setViewportStartAndWidth(-1, 7);
+ assertEquals(vr.getViewportWidth(), 7);
+ assertEquals(vr.getStartRes(), 0);
+
+ // out of bounds values are not forced to within bounds
+ vr.setViewportStartAndWidth(35, 5);
+ assertEquals(vr.getViewportWidth(), 5);
+ assertEquals(vr.getStartRes(), 35);
+
+ // small alignment doesn't get bounds reset
+ ViewportRanges vrsmall = new ViewportRanges(smallAl);
+ vrsmall.setViewportStartAndWidth(0, 63);
+ assertEquals(vrsmall.getViewportWidth(), 7);
+ assertEquals(vrsmall.getStartRes(), 0);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetWrappedMaxScroll()
+ {
+ // generate an ungapped alignment of width 140
+ int alignmentWidth = 140;
+ AlignmentI al2 = gen.generate(alignmentWidth, 15, 1, 0, 5);
+ ViewportRanges vr = new ViewportRanges(al2);
+ vr.setStartEndRes(0, 39);
+ int width = vr.getViewportWidth(); // 40
+ int partWidth = alignmentWidth % width; // 20
+
+ /*
+ * there are 3 * 40 remainder 20 residues
+ * number of widths depends on offset (scroll right)
+ * 4 widths (maxScroll = 3) if offset by 0 or more than 19 columns
+ * 5 widths (maxScroll = 4) if 1 <= offset <= 19
+ */
+ for (int col = 0; col < alignmentWidth; col++)
+ {
+ int offset = col % width;
+ if (offset > 0 && offset < partWidth)
+ {
+ assertEquals(vr.getWrappedMaxScroll(col), 4, "col " + col);
+ }
+ else
+ {
+ assertEquals(vr.getWrappedMaxScroll(col), 3, "col " + col);
+ }
+ }
+ }
}
// mock listener for property change events