label.your_sequences_have_been_verified = Your sequences have been verified against known sequence databases.\n(Use Calculate | Show flanking regions to show enclosing sequence.)\nTo preserve data changes, save your alignment.\n\n
label.sequences_updated = Sequences updated
label.dbref_search_completed = DBRef search completed
-label.show_all_chains = Show all chains
label.fetch_all_param = Fetch all {0}
label.paste_new_window = Paste To New Window
label.settings_for_param = Settings for {0}
label.SEQUENCE_ID_for_DB_ACCESSION1 = Please review your URL links in the 'Connections' tab of the Preferences window:
label.SEQUENCE_ID_for_DB_ACCESSION2 = URL links using '$SEQUENCE_ID$' for DB accessions now use '$DB_ACCESSION$'.
label.do_not_display_again = Do not display this message again
-exception.url_cannot_have_miriam_id = {0} is a MIRIAM id and cannot be used as a custom url name
exception.url_cannot_have_duplicate_id = {0} cannot be used as a label for more than one line
label.filter = Filter text:
action.customfilter = Custom only
label.your_sequences_have_been_verified = Sus secuencias has sido verificadas en una base de datos de secuencias conocidas.\n(Usar Calcular | Mostrar flancos para ver ampliación.)\nPara mantener los datos actualizados, guarde su alineamiento.\n\n
label.sequences_updated = Secuencias actualizadas
label.dbref_search_completed = Búsqueda de DBRef terminada
-label.show_all_chains = Mostrar todas las cadenas
label.fetch_all_param = Recuperar todas {0}
label.paste_new_window = Pegar en una nueva ventana
label.settings_for_param = Configuración para {0}
label.SEQUENCE_ID_for_DB_ACCESSION1 = Por favor, revise sus URLs en la pestaña 'Conexiones' de la ventana de Preferencias:
label.SEQUENCE_ID_for_DB_ACCESSION2 = URL enlaza usando '$SEQUENCE_ID$' para accesiones DB ahora usar '$DB_ACCESSION$'.
label.do_not_display_again = No mostrar este mensaje de nuevo
-exception.url_cannot_have_miriam_id = {0} es una id MIRIAM y no puede ser usada como nombre url personalizado
exception.url_cannot_have_duplicate_id = {0} no puede ser usada como etiqueta en más de un enlace
label.filter = Filtrar texto:
action.customfilter = Sólo personalizado
label.invalid_name = Nombre inválido !
label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas
label.urllinks = Enlaces
+label.default_cache_size = Tamaño del caché por defecto
+action.clear_cached_items = Borrar elementos en caché
label.quality_descr = Calidad de alineamiento basándose en puntuación Blosum62
label.conservation_descr = Conservación del alineamiento total menos de {0}% huecos
label.consensus_descr = % Identidad
label.complement_consensus_descr = % Identidad para cDNA
label.strucconsensus_descr = % Identidad para pares de bases
label.occupancy_descr = Número de posiciones alineadas
-label.togglehidden = Show hidden regions
+label.togglehidden = Mostrar regiones ocultas
+label.show_experimental = Habilitar funciones experimentales
+label.show_experimental_tip = Habilitar funciones nuevas y experimentales (ver Latest Release Notes para más detalles)
label.warning_hidden = Advertencia: {0} {1} está actualmente oculto
}
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();
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
- int newX = offy * rowSize;
- if ((newX == oldX) && (oldwidth == rowSize))
- {
- return;
- }
- else if (offy > -1)
- {
- /*
- * throttle to one width's worth at a time (so click in
- * scrollbar doesn't jump over data)
- */
- newX = newX > oldX ? oldX + rowSize : oldX - rowSize;
- vpRanges.setViewportStartAndWidth(newX, 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);
}
/**
*/
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,
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);
}
int annotationHeight = getAnnotationHeight();
{
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.labelWidthWest;
+ x = Math.max(0, x - seqCanvas.labelWidthWest);
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
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;
}
}
{
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());
+ }
}
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