</p>
<table>
<tr>
- <td><img src="AnnotationColumnSelectionWithSM.gif"></td>
+ <td><img src="AnnotationColumnSelectionWithSM.png"></td>
<td><img src="AnnotationColumnSelectionWithoutSM.gif"></td>
</tr>
</table>
<li>Select whether to filter the alignment above or below
the threshold.</li>
<li>Change the threshold value with the slider, or enter it
- in the text box.</li>
+ in the text box.
+ <li>The <em>As Percentage</em> checkbox allows thresholds to
+ be set as a percentage rather than absolute value.</li>
</ul>
<li><strong>Actions</strong>
<ul>
<ul>
<li>
<!-- JAL-2398, -->Fixed incorrect value in BLOSUM 62 score
- matrix - C->R should be '3'<br />Old matrix restored with
+ matrix - C->R should be '-3'<br />Old matrix restored with
this one-line groovy script:<br />jalview.analysis.scoremodels.ScoreModels.instance.BLOSUM62.@matrix[4][1]=3
</li>
<li>
earlier versions of Jalview, gaps matching gaps were
penalised, and gaps matching non-gaps penalised even more.
In the PCA calculation, gaps were actually treated as
- non-gaps - so different costs were applied, which mean't
+ non-gaps - so different costs were applied, which meant
Jalview's PCAs were different to those produced by
SeqSpace.<br />Jalview now treats gaps in the same way as
SeqSpace (ie it scores them as 0). To restore pre-2.10.2
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
boolean hasThreshold();
/**
- * Returns the computed colour for the given sequence feature
+ * Returns the computed colour for the given sequence feature. Answers null if
+ * the score of this feature instance is outside the range to render (if any),
+ * i.e. lies below or above a configured threshold.
*
* @param feature
* @return
Color getColor(SequenceFeature feature);
/**
- * Answers true if the feature has a simple colour, or is coloured by label,
- * or has a graduated colour and the score of this feature instance is within
- * the range to render (if any), i.e. does not lie below or above any
- * threshold set.
- *
- * @param feature
- * @return
- */
- boolean isColored(SequenceFeature feature);
-
- /**
* Update the min-max range for a graduated colour scheme
*
* @param min
}
}
- if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
- features, true, ap))
+ if (!seqs.isEmpty())
{
- ap.alignFrame.sequenceFeatures.setState(true);
- ap.av.setShowSequenceFeatures(true);
- ap.highlightSearchResults(null);
+ if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
+ features, true, ap))
+ {
+ ap.alignFrame.sequenceFeatures.setState(true);
+ ap.av.setShowSequenceFeatures(true);
+ ap.av.setSearchResults(null); // clear highlighting
+ ap.repaint(); // draw new/amended features
+ }
}
}
else
}
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:
synchronized void slideSequences(boolean right, int size)
{
- List<SequenceI> sg = new Vector<SequenceI>();
+ List<SequenceI> sg = new Vector<>();
if (viewport.cursorMode)
{
sg.add(viewport.getAlignment().getSequenceAt(
static StringBuffer copiedSequences;
- static Vector copiedHiddenColumns;
+ static Vector<int[]> copiedHiddenColumns;
protected void copy_actionPerformed()
{
SequenceGroup sg = viewport.getSelectionGroup();
copiedSequences = new StringBuffer();
- Map<Integer, SequenceI> orderedSeqs = new HashMap<Integer, SequenceI>();
+ Map<Integer, SequenceI> orderedSeqs = new HashMap<>();
for (int i = 0; i < sg.getSize(); i++)
{
SequenceI seq = sg.getSequenceAt(i);
if (viewport.hasHiddenColumns() && viewport.getSelectionGroup() != null)
{
- copiedHiddenColumns = new Vector();
+ copiedHiddenColumns = new Vector<>(viewport.getAlignment()
+ .getHiddenColumns().getHiddenColumnsCopy());
int hiddenOffset = viewport.getSelectionGroup().getStartRes();
- for (int[] region : viewport.getAlignment().getHiddenColumns()
- .getHiddenRegions())
+ for (int[] region : copiedHiddenColumns)
{
- copiedHiddenColumns.addElement(new int[] {
- region[0] - hiddenOffset, region[1] - hiddenOffset });
+ region[0] = region[0] - hiddenOffset;
+ region[1] = region[1] - hiddenOffset;
}
}
else
{
for (int i = 0; i < copiedHiddenColumns.size(); i++)
{
- int[] region = (int[]) copiedHiddenColumns.elementAt(i);
+ int[] region = copiedHiddenColumns.elementAt(i);
af.viewport.hideColumns(region[0], region[1]);
}
}
}
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);
import jalview.bin.JalviewLite;
import jalview.commands.CommandI;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResults;
}
- /**
- * get the consensus sequence as displayed under the PID consensus annotation
- * row.
- *
- * @return consensus sequence as a new sequence object
- */
- public SequenceI getConsensusSeq()
- {
- if (consensus == null)
- {
- updateConsensus(null);
- }
- if (consensus == null)
- {
- return null;
- }
- StringBuilder seqs = new StringBuilder(consensus.annotations.length);
- for (int i = 0; i < consensus.annotations.length; i++)
- {
- if (consensus.annotations[i] != null)
- {
- if (consensus.annotations[i].description.charAt(0) == '[')
- {
- seqs.append(consensus.annotations[i].description.charAt(1));
- }
- else
- {
- seqs.append(consensus.annotations[i].displayCharacter);
- }
- }
- }
- SequenceI sq = new Sequence("Consensus", seqs.toString());
- sq.setDescription("Percentage Identity Consensus "
- + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
- return sq;
- }
-
java.awt.Frame nullFrame;
protected FeatureSettings featureSettings = 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();
import java.awt.event.MouseListener;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
-import java.util.Iterator;
+import java.util.ArrayList;
import java.util.Vector;
//import javax.swing.JPanel;
}
setOldHiddenColumns(av.getAlignment().getHiddenColumns());
adjusting = true;
- Vector<String> list = new Vector<String>();
+ Vector<String> list = new Vector<>();
int index = 1;
for (int i = 0; i < anns.length; i++)
{
HiddenColumns oldHidden = av
.getAnnotationColumnSelectionState()
.getOldHiddenColumns();
- if (oldHidden != null && oldHidden.getHiddenRegions() != null
- && !oldHidden.getHiddenRegions().isEmpty())
+ if (oldHidden != null)
{
- for (Iterator<int[]> itr = oldHidden.getHiddenRegions()
- .iterator(); itr.hasNext();)
+ ArrayList<int[]> regions = oldHidden.getHiddenColumnsCopy();
+ for (int[] positions : regions)
{
- int positions[] = itr.next();
av.hideColumns(positions[0], positions[1]);
}
}
+ // TODO not clear why we need to hide all the columns (above) if we are
+ // going to copy the hidden columns over wholesale anyway
av.getAlignment().setHiddenColumns(oldHidden);
}
av.sendSelection();
+ sq.getSequenceAsString() + "\n");
if (av.hasHiddenColumns())
{
- jalview.appletgui.AlignFrame.copiedHiddenColumns = new Vector();
- for (int[] region : av.getAlignment().getHiddenColumns()
- .getHiddenRegions())
- {
- jalview.appletgui.AlignFrame.copiedHiddenColumns
- .addElement(new int[] { region[0], region[1] });
- }
+ jalview.appletgui.AlignFrame.copiedHiddenColumns = new Vector<>(
+ av.getAlignment().getHiddenColumns()
+ .getHiddenColumnsCopy());
}
}
import jalview.util.MessageManager;
import jalview.util.Platform;
import jalview.viewmodel.ViewportListenerI;
+import jalview.viewmodel.ViewportRanges;
import java.awt.Color;
import java.awt.Dimension;
// ap.annotationScroller.getVAdjustable().addAdjustmentListener( this );
renderer = new AnnotationRenderer();
+
+ av.getRanges().addPropertyChangeListener(this);
}
public AnnotationPanel(AlignViewport av)
{
this.av = av;
renderer = new AnnotationRenderer();
- av.getRanges().addPropertyChangeListener(this);
+
}
@Override
public void propertyChange(PropertyChangeEvent evt)
{
// Respond to viewport range changes (e.g. alignment panel was scrolled)
- if (evt.getPropertyName().equals("startres")
- || evt.getPropertyName().equals("endres"))
+ // 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.STARTRES))
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
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;
if (!colourPanel.isGcol)
{
// update colour - otherwise its already done.
- setColour(sf.type, new FeatureColour(colourPanel.getBackground()));
+ setColour(enteredType,
+ new FeatureColour(colourPanel.getBackground()));
}
int newBegin = sf.begin;
int newEnd = sf.end;
* (to ensure integrity of SequenceFeatures data store)
*/
sequences.get(0).deleteFeature(sf);
- SequenceFeature newSf = new SequenceFeature(sf, newBegin, newEnd,
- enteredGroup, sf.getScore());
+ SequenceFeature newSf = new SequenceFeature(sf, enteredType,
+ newBegin, newEnd, enteredGroup, sf.getScore());
newSf.setDescription(enteredDesc);
ffile.parseDescriptionHTML(newSf, false);
// amend features dialog only updates one sequence at a time
sequences.get(0).addSequenceFeature(newSf);
- boolean typeOrGroupChanged = (!featureType.equals(sf.type) || !featureGroup
- .equals(sf.featureGroup));
+ boolean typeOrGroupChanged = (!featureType.equals(newSf.getType()) || !featureGroup
+ .equals(newSf.getFeatureGroup()));
ffile.parseDescriptionHTML(sf, false);
if (typeOrGroupChanged)
Set<String> visibleGroups = new HashSet<String>();
for (String group : groups)
{
- if (group == null || fr.checkGroupVisibility(group, true))
+ // if (group == null || fr.checkGroupVisibility(group, true))
+ if (group == null || checkGroupState(group))
{
visibleGroups.add(group);
}
}
+ foundGroups.addAll(groups);
/*
* get distinct feature types for visible groups
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)
- if (evt.getPropertyName().equals("startseq")
- || evt.getPropertyName().equals("endseq"))
+ String propertyName = evt.getPropertyName();
+ if (propertyName.equals(ViewportRanges.STARTSEQ)
+ || (av.getWrapAlignment() && propertyName
+ .equals(ViewportRanges.STARTRES)))
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
private OverviewDimensions od;
+ private OverviewRenderer or = null;
+
private Image miniMe;
private Image offscreen;
if (updaterunning)
{
restart = true;
+ if (or != null)
+ {
+ or.setRedraw(true);
+ }
}
else
{
setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
- OverviewRenderer or = new OverviewRenderer(sr, fr, od);
+ or = new OverviewRenderer(sr, fr, od);
miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
*/
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;
+ }
+ }
}
import jalview.renderer.ScaleRenderer.ScaleMark;
import jalview.util.MessageManager;
import jalview.viewmodel.ViewportListenerI;
+import jalview.viewmodel.ViewportRanges;
import java.awt.Color;
import java.awt.FontMetrics;
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();
}
});
int res = (evt.getX() / av.getCharWidth())
+ av.getRanges().getStartRes();
- res = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(res);
-
- reveal = null;
- for (int[] region : av.getAlignment().getHiddenColumns()
- .getHiddenRegions())
- {
- if (res + 1 == region[0] || res - 1 == region[1])
- {
- reveal = region;
- break;
- }
- }
+ reveal = av.getAlignment().getHiddenColumns()
+ .getRegionWithEdgeAtRes(res);
repaint();
}
@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,
if (av.getShowHiddenMarkers())
{
int widthx = 1 + endx - startx;
- for (int i = 0; i < hidden.getHiddenRegions().size(); i++)
+ List<Integer> positions = hidden.findHiddenRegionPositions();
+ for (int pos : positions)
{
- res = hidden.findHiddenRegionPosition(i) - startx;
+ res = pos - startx;
if (res < 0 || res > widthx)
{
public void propertyChange(PropertyChangeEvent evt)
{
// Respond to viewport change events (e.g. alignment panel was scrolled)
- repaint();
+ // 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.STARTRES))
+ {
+ // scroll event, repaint panel
+ repaint();
+ }
}
}
import java.awt.Image;
import java.awt.Panel;
import java.beans.PropertyChangeEvent;
+import java.util.List;
public class SeqCanvas extends Panel implements ViewportListenerI
{
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))
HiddenColumns hidden = av.getAlignment().getHiddenColumns();
g.setColor(Color.blue);
int res;
- for (int i = 0; i < hidden.getHiddenRegions()
- .size(); i++)
+ List<Integer> positions = hidden.findHiddenRegionPositions();
+ for (int pos : positions)
{
- res = hidden.findHiddenRegionPosition(i)
- - startRes;
+ res = pos - startRes;
if (res < 0 || res > endx - startRes)
{
if (av.hasHiddenColumns())
{
HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- for (int[] region : hidden.getHiddenRegions())
+ for (int[] region : hidden.getHiddenColumnsCopy())
{
int hideStart = region[0];
int hideEnd = region[1];
@Override
public void propertyChange(PropertyChangeEvent evt)
{
+ String eventName = evt.getPropertyName();
+
if (!av.getWrapAlignment())
{
- if (evt.getPropertyName().equals("startres")
- || evt.getPropertyName().equals("endres"))
+ int scrollX = 0;
+ if (eventName.equals(ViewportRanges.STARTRES))
{
// Make sure we're not trying to draw a panel
// larger than the visible window
ViewportRanges vpRanges = av.getRanges();
- int scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
- if (scrollX > vpRanges.getEndRes() - vpRanges.getStartRes())
+ scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+ int range = vpRanges.getEndRes() - vpRanges.getStartRes();
+ if (scrollX > range)
{
- scrollX = vpRanges.getEndRes() - vpRanges.getStartRes();
+ scrollX = range;
}
- else if (scrollX < vpRanges.getStartRes() - vpRanges.getEndRes())
+ else if (scrollX < -range)
{
- scrollX = vpRanges.getStartRes() - vpRanges.getEndRes();
+ scrollX = -range;
}
+ }
+
+ // 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 (eventName.equals(ViewportRanges.STARTRES))
+ {
+ // scroll - startres and endres both change
fastPaint(scrollX, 0);
}
- else if (evt.getPropertyName().equals("startseq")
- || evt.getPropertyName().equals("endseq"))
+ else if (eventName.equals(ViewportRanges.STARTSEQ))
{
+ // scroll
fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
}
}
-
}
}
seqCanvas.highlightSearchResults(highlight);
seqCanvas.getFeatureRenderer().amendFeatures(
Collections.singletonList(sequence), features, false, ap);
- seqCanvas.highlightSearchResults(null);
+ av.setSearchResults(null); // clear highlighting
+ seqCanvas.repaint(); // draw new/amended features
}
}
}
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())
// Find the next gap before the end
// of the visible region boundary
boolean blank = false;
- for (fixedRight = fixedRight; fixedRight > lastres; fixedRight--)
+ for (; fixedRight > lastres; fixedRight--)
{
blank = true;
}
if (copycolsel
&& av.hasHiddenColumns()
- && (av.getColumnSelection() == null || av.getAlignment()
- .getHiddenColumns().getHiddenRegions() == null))
+ && (av.getColumnSelection() == null))
{
System.err.println("Bad things");
}
*/
package jalview.appletgui;
+import jalview.analysis.Conservation;
import jalview.datamodel.SequenceGroup;
import jalview.renderer.ResidueShaderI;
import jalview.util.MessageManager;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
-import java.util.Iterator;
+import java.util.List;
public class SliderPanel extends Panel implements ActionListener,
AdjustmentListener, MouseListener
conservationSlider.setTitle(MessageManager.formatMessage(
"label.conservation_colour_increment",
new String[] { source == null ? BACKGROUND : source }));
- if (ap.av.getAlignment().getGroups() != null)
+ List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
+ if (groups != null && !groups.isEmpty())
{
sp.setAllGroupsCheckEnabled(true);
}
{
return;
}
-
- ResidueShaderI toChange = cs;
- Iterator<SequenceGroup> allGroups = null;
-
- if (allGroupsCheck.getState())
+ if (forConservation)
{
- allGroups = ap.av.getAlignment().getGroups().listIterator();
+ cs.setConservationApplied(true);
+ cs.setConservationInc(i);
+ }
+ else
+ {
+ cs.setThreshold(i, ap.av.isIgnoreGapsConsensus());
}
- while (toChange != null)
+ if (allGroupsCheck.getState())
{
- if (forConservation)
+ for (SequenceGroup group : ap.av.getAlignment().getGroups())
{
- toChange.setConservationInc(i);
- }
- else
- {
- toChange.setThreshold(i, ap.av.isIgnoreGapsConsensus());
- }
- if (allGroups != null && allGroups.hasNext())
- {
- while ((toChange = allGroups.next().cs) == null
- && allGroups.hasNext())
+ ResidueShaderI groupColourScheme = group.getGroupColourScheme();
+ if (forConservation)
{
- ;
+ if (!groupColourScheme.conservationApplied())
+ {
+ /*
+ * first time the colour scheme has had Conservation shading applied
+ * - compute conservation
+ */
+ Conservation c = new Conservation("Group",
+ group.getSequences(null), group.getStartRes(),
+ group.getEndRes());
+ c.calculate();
+ c.verdict(false, ap.av.getConsPercGaps());
+ group.cs.setConservation(c);
+
+ }
+ groupColourScheme.setConservationApplied(true);
+ groupColourScheme.setConservationInc(i);
+ }
+ else
+ {
+ groupColourScheme.setThreshold(i, ap.av.isIgnoreGapsConsensus());
}
- }
- else
- {
- toChange = null;
}
}
ap.seqPanel.seqCanvas.repaint();
-
}
public void setAllGroupsCheckEnabled(boolean b)
{
+ allGroupsCheck.setState(ap.av.getColourAppliesToAllGroups());
allGroupsCheck.setEnabled(b);
}
}
@Override
- public int[] getVisibleStartAndEndIndex(List<int[]> hiddenCols)
- {
- int[] alignmentStartEnd = new int[] { 0, getWidth() - 1 };
- int startPos = alignmentStartEnd[0];
- int endPos = alignmentStartEnd[1];
-
- int[] lowestRange = new int[] { -1, -1 };
- int[] higestRange = new int[] { -1, -1 };
-
- for (int[] hiddenCol : hiddenCols)
- {
- lowestRange = (hiddenCol[0] <= startPos) ? hiddenCol : lowestRange;
- higestRange = (hiddenCol[1] >= endPos) ? hiddenCol : higestRange;
- }
-
- if (lowestRange[0] == -1 && lowestRange[1] == -1)
- {
- startPos = alignmentStartEnd[0];
- }
- else
- {
- startPos = lowestRange[1] + 1;
- }
-
- if (higestRange[0] == -1 && higestRange[1] == -1)
- {
- endPos = alignmentStartEnd[1];
- }
- else
- {
- endPos = higestRange[0] - 1;
- }
- return new int[] { startPos, endPos };
- }
-
- @Override
public void setHiddenColumns(HiddenColumns cols)
{
hiddenCols = cols;
*/
AlignedCodonFrame getMapping(SequenceI mapFrom, SequenceI mapTo);
- /**
- * Calculate the visible start and end index of an alignment. The result is
- * returned an int array where: int[0] = startIndex, and int[1] = endIndex.
- *
- * @param hiddenCols
- * @return
- */
- public int[] getVisibleStartAndEndIndex(List<int[]> hiddenCols);
-
public void setHiddenColumns(HiddenColumns cols);
}
{
int nores = (isNa) ? ResidueProperties.maxNucleotideIndex
: ResidueProperties.maxProteinIndex;
+
dbinary = new double[getLength() * nores];
return nores;
{
int nores = initMatrixGetNoRes();
- for (int i = 0, iSize = getSequence().length; i < iSize; i++)
+ for (int i = 0, iSize = getLength(); i < iSize; i++)
{
int aanum = nores - 1;
{
this(constructSeqCigarArray(alignment, selectionGroup));
constructFromAlignment(alignment,
- hidden != null ? hidden.getHiddenRegions()
+ hidden != null ? hidden.getHiddenColumnsCopy()
: null, selectionGroup);
}
*/
public void invertColumnSelection(int first, int width, AlignmentI al)
{
- boolean hasHidden = al.getHiddenColumns().hasHidden();
+ boolean hasHidden = al.getHiddenColumns().hasHiddenColumns();
for (int i = first; i < width; i++)
{
if (contains(i))
selection = new IntList();
if (colsel.selection != null && colsel.selection.size() > 0)
{
- if (hiddenColumns.hasHidden())
+ if (hiddenColumns.hasHiddenColumns())
{
// only select visible columns in this columns selection
for (Integer col : colsel.getSelected())
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
package jalview.datamodel;
import jalview.util.Comparison;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
public class HiddenColumns
{
+ private static final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();
+
/*
* list of hidden column [start, end] ranges; the list is maintained in
* ascending start column order
*/
- private Vector<int[]> hiddenColumns;
+ private ArrayList<int[]> hiddenColumns;
/**
- * This Method is used to return all the HiddenColumn regions
- *
- * @return empty list or List of hidden column intervals
+ * Constructor
*/
- public List<int[]> getHiddenRegions()
+ public HiddenColumns()
{
- return hiddenColumns == null ? Collections.<int[]> emptyList()
- : hiddenColumns;
}
/**
- * Find the number of hidden columns
+ * Copy constructor
*
- * @return number of hidden columns
+ * @param copy
*/
- public int getSize()
+ public HiddenColumns(HiddenColumns copy)
{
- int size = 0;
- if (hasHidden())
+ try
{
- for (int[] range : hiddenColumns)
+ LOCK.writeLock().lock();
+ if (copy != null)
{
- size += range[1] - range[0] + 1;
+ if (copy.hiddenColumns != null)
+ {
+ hiddenColumns = copy.copyHiddenRegionsToArrayList();
+ }
}
+ } finally
+ {
+ LOCK.writeLock().unlock();
}
- return size;
}
/**
- * Answers if there are any hidden columns
+ * This method is used to return all the HiddenColumn regions and is intended
+ * to remain private. External callers which need a copy of the regions can
+ * call getHiddenColumnsCopyAsList.
*
- * @return true if there are hidden columns
+ * @return empty list or List of hidden column intervals
*/
- public boolean hasHidden()
+ private List<int[]> getHiddenRegions()
{
- return (hiddenColumns != null) && (!hiddenColumns.isEmpty());
+ return hiddenColumns == null ? Collections.<int[]> emptyList()
+ : hiddenColumns;
}
- @Override
- public boolean equals(Object obj)
+ /**
+ * Output regions data as a string. String is in the format:
+ * reg0[0]<between>reg0[1]<delimiter>reg1[0]<between>reg1[1] ... regn[1]
+ *
+ * @param delimiter
+ * string to delimit regions
+ * @param betweenstring
+ * to put between start and end region values
+ * @return regions formatted according to delimiter and between strings
+ */
+ public String regionsToString(String delimiter, String between)
{
- if (!(obj instanceof HiddenColumns))
+ try
+ {
+ LOCK.readLock().lock();
+ StringBuilder regionBuilder = new StringBuilder();
+ if (hiddenColumns != null)
+ {
+ for (int[] range : hiddenColumns)
+ {
+ regionBuilder.append(delimiter).append(range[0]).append(between)
+ .append(range[1]);
+ }
+
+ regionBuilder.deleteCharAt(0);
+ }
+ return regionBuilder.toString();
+ } finally
{
- return false;
+ LOCK.readLock().unlock();
}
- HiddenColumns that = (HiddenColumns) obj;
+ }
- /*
- * check hidden columns are either both null, or match
- */
- if (this.hiddenColumns == null)
+ /**
+ * Find the number of hidden columns
+ *
+ * @return number of hidden columns
+ */
+ public int getSize()
+ {
+ try
{
- return (that.hiddenColumns == null);
+ LOCK.readLock().lock();
+ int size = 0;
+ if (hasHiddenColumns())
+ {
+ for (int[] range : hiddenColumns)
+ {
+ size += range[1] - range[0] + 1;
+ }
+ }
+ return size;
}
- if (that.hiddenColumns == null
- || that.hiddenColumns.size() != this.hiddenColumns.size())
+ finally
{
- return false;
+ LOCK.readLock().unlock();
}
- int i = 0;
- for (int[] thisRange : hiddenColumns)
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ try
{
- int[] thatRange = that.hiddenColumns.get(i++);
- if (thisRange[0] != thatRange[0] || thisRange[1] != thatRange[1])
+ LOCK.readLock().lock();
+
+ if (!(obj instanceof HiddenColumns))
+ {
+ return false;
+ }
+ HiddenColumns that = (HiddenColumns) obj;
+
+ /*
+ * check hidden columns are either both null, or match
+ */
+ if (this.hiddenColumns == null)
+ {
+ return (that.hiddenColumns == null);
+ }
+ if (that.hiddenColumns == null
+ || that.hiddenColumns.size() != this.hiddenColumns.size())
{
return false;
}
+ int i = 0;
+ for (int[] thisRange : hiddenColumns)
+ {
+ int[] thatRange = that.hiddenColumns.get(i++);
+ if (thisRange[0] != thatRange[0] || thisRange[1] != thatRange[1])
+ {
+ return false;
+ }
+ }
+ return true;
+ } finally
+ {
+ LOCK.readLock().unlock();
}
- return true;
}
/**
*/
public int adjustForHiddenColumns(int column)
{
- int result = column;
- if (hiddenColumns != null)
+ try
{
- for (int i = 0; i < hiddenColumns.size(); i++)
+ LOCK.readLock().lock();
+ int result = column;
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(i);
- if (result >= region[0])
+ for (int i = 0; i < hiddenColumns.size(); i++)
{
- result += region[1] - region[0] + 1;
+ int[] region = hiddenColumns.get(i);
+ if (result >= region[0])
+ {
+ result += region[1] - region[0] + 1;
+ }
}
}
+ return result;
+ } finally
+ {
+ LOCK.readLock().unlock();
}
- return result;
}
/**
*/
public int findColumnPosition(int hiddenColumn)
{
- int result = hiddenColumn;
- if (hiddenColumns != null)
+ try
{
- int index = 0;
- int[] region;
- do
+ LOCK.readLock().lock();
+ int result = hiddenColumn;
+ if (hiddenColumns != null)
{
- region = hiddenColumns.elementAt(index++);
- if (hiddenColumn > region[1])
+ int index = 0;
+ int[] region;
+ do
{
- result -= region[1] + 1 - region[0];
- }
- } while ((hiddenColumn > region[1]) && (index < hiddenColumns.size()));
+ region = hiddenColumns.get(index++);
+ if (hiddenColumn > region[1])
+ {
+ result -= region[1] + 1 - region[0];
+ }
+ } while ((hiddenColumn > region[1])
+ && (index < hiddenColumns.size()));
- if (hiddenColumn >= region[0] && hiddenColumn <= region[1])
- {
- // Here the hidden column is within a region, so
- // we want to return the position of region[0]-1, adjusted for any
- // earlier hidden columns.
- // Calculate the difference between the actual hidden col position
- // and region[0]-1, and then subtract from result to convert result from
- // the adjusted hiddenColumn value to the adjusted region[0]-1 value
-
- // However, if the region begins at 0 we cannot return region[0]-1
- // just return 0
- if (region[0] == 0)
- {
- return 0;
- }
- else
+ if (hiddenColumn >= region[0] && hiddenColumn <= region[1])
{
- return result - (hiddenColumn - region[0] + 1);
+ // Here the hidden column is within a region, so
+ // we want to return the position of region[0]-1, adjusted for any
+ // earlier hidden columns.
+ // Calculate the difference between the actual hidden col position
+ // and region[0]-1, and then subtract from result to convert result
+ // from
+ // the adjusted hiddenColumn value to the adjusted region[0]-1 value
+
+ // However, if the region begins at 0 we cannot return region[0]-1
+ // just return 0
+ if (region[0] == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return result - (hiddenColumn - region[0] + 1);
+ }
}
}
+ return result; // return the shifted position after removing hidden
+ // columns.
+ } finally
+ {
+ LOCK.readLock().unlock();
}
- return result; // return the shifted position after removing hidden columns.
}
/**
*/
public int subtractVisibleColumns(int visibleDistance, int startColumn)
{
+ try
+ {
+
+ LOCK.readLock().lock();
int distance = visibleDistance;
// in case startColumn is in a hidden region, move it to the left
return nextstart - distance;
}
return start - distance;
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
}
/**
- * Use this method to determine where the next hiddenRegion starts
+ * Use this method to determine the set of hiddenRegion start positions
*
- * @param hiddenRegion
- * index of hidden region (counts from 0)
- * @return column number in visible view
+ * @return list of column number in visible view where hidden regions start
*/
- public int findHiddenRegionPosition(int hiddenRegion)
+ public List<Integer> findHiddenRegionPositions()
{
- int result = 0;
- if (hiddenColumns != null)
+ try
{
- int index = 0;
- int gaps = 0;
- do
+ LOCK.readLock().lock();
+ List<Integer> positions = null;
+
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(index);
- if (hiddenRegion == 0)
+ positions = new ArrayList<>(hiddenColumns.size());
+
+ positions.add(hiddenColumns.get(0)[0]);
+ for (int i = 1; i < hiddenColumns.size(); ++i)
{
- return region[0];
- }
- gaps += region[1] + 1 - region[0];
- result = region[1] + 1;
- index++;
- } while (index <= hiddenRegion);
+ int result = 0;
+ if (hiddenColumns != null)
+ {
+ int index = 0;
+ int gaps = 0;
+ do
+ {
+ int[] region = hiddenColumns.get(index);
+ gaps += region[1] + 1 - region[0];
+ result = region[1] + 1;
+ index++;
+ } while (index <= i);
- result -= gaps;
- }
+ result -= gaps;
+ }
+ positions.add(result);
+ }
+ }
+ else
+ {
+ positions = new ArrayList<>();
+ }
- return result;
+ return positions;
+ }
+ finally
+ {
+ LOCK.readLock().unlock();
+ }
}
/**
*/
public int getHiddenBoundaryRight(int alPos)
{
- if (hiddenColumns != null)
+ try
{
- int index = 0;
- do
+ LOCK.readLock().lock();
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(index);
- if (alPos < region[0])
+ int index = 0;
+ do
{
- return region[0];
- }
+ int[] region = hiddenColumns.get(index);
+ if (alPos < region[0])
+ {
+ return region[0];
+ }
- index++;
- } while (index < hiddenColumns.size());
- }
+ index++;
+ } while (index < hiddenColumns.size());
+ }
- return alPos;
+ return alPos;
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
}
*/
public int getHiddenBoundaryLeft(int alPos)
{
+ try
+ {
+ LOCK.readLock().lock();
+
if (hiddenColumns != null)
{
int index = hiddenColumns.size() - 1;
do
{
- int[] region = hiddenColumns.elementAt(index);
+ int[] region = hiddenColumns.get(index);
if (alPos > region[1])
{
return region[1];
}
return alPos;
-
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
}
/**
*/
private int getHiddenIndexLeft(int pos)
{
+ try
+ {
+
+ LOCK.readLock().lock();
if (hiddenColumns != null)
{
int index = hiddenColumns.size() - 1;
do
{
- int[] region = hiddenColumns.elementAt(index);
+ int[] region = hiddenColumns.get(index);
if (pos > region[1])
{
return index;
}
return -1;
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
}
*/
public void hideColumns(int start, int end)
{
- if (hiddenColumns == null)
- {
- hiddenColumns = new Vector<int[]>();
- }
-
- /*
- * traverse existing hidden ranges and insert / amend / append as
- * appropriate
- */
- for (int i = 0; i < hiddenColumns.size(); i++)
+ boolean wasAlreadyLocked = false;
+ try
{
- int[] region = hiddenColumns.elementAt(i);
-
- if (end < region[0] - 1)
+ // check if the write lock was already locked by this thread,
+ // as this method can be called internally in loops within HiddenColumns
+ if (!LOCK.isWriteLockedByCurrentThread())
{
- /*
- * insert discontiguous preceding range
- */
- hiddenColumns.insertElementAt(new int[] { start, end }, i);
- return;
+ LOCK.writeLock().lock();
+ }
+ else
+ {
+ wasAlreadyLocked = true;
}
- if (end <= region[1])
+ if (hiddenColumns == null)
{
- /*
- * new range overlaps existing, or is contiguous preceding it - adjust
- * start column
- */
- region[0] = Math.min(region[0], start);
- return;
+ hiddenColumns = new ArrayList<>();
}
- if (start <= region[1] + 1)
+ /*
+ * traverse existing hidden ranges and insert / amend / append as
+ * appropriate
+ */
+ for (int i = 0; i < hiddenColumns.size(); i++)
{
- /*
- * new range overlaps existing, or is contiguous following it - adjust
- * start and end columns
- */
- region[0] = Math.min(region[0], start);
- region[1] = Math.max(region[1], end);
-
- /*
- * also update or remove any subsequent ranges
- * that are overlapped
- */
- while (i < hiddenColumns.size() - 1)
+ int[] region = hiddenColumns.get(i);
+
+ if (end < region[0] - 1)
+ {
+ /*
+ * insert discontiguous preceding range
+ */
+ hiddenColumns.add(i, new int[] { start, end });
+ return;
+ }
+
+ if (end <= region[1])
+ {
+ /*
+ * new range overlaps existing, or is contiguous preceding it - adjust
+ * start column
+ */
+ region[0] = Math.min(region[0], start);
+ return;
+ }
+
+ if (start <= region[1] + 1)
{
- int[] nextRegion = hiddenColumns.get(i + 1);
- if (nextRegion[0] > end + 1)
+ /*
+ * new range overlaps existing, or is contiguous following it - adjust
+ * start and end columns
+ */
+ region[0] = Math.min(region[0], start);
+ region[1] = Math.max(region[1], end);
+
+ /*
+ * also update or remove any subsequent ranges
+ * that are overlapped
+ */
+ while (i < hiddenColumns.size() - 1)
{
- /*
- * gap to next hidden range - no more to update
- */
- break;
+ int[] nextRegion = hiddenColumns.get(i + 1);
+ if (nextRegion[0] > end + 1)
+ {
+ /*
+ * gap to next hidden range - no more to update
+ */
+ break;
+ }
+ region[1] = Math.max(nextRegion[1], end);
+ hiddenColumns.remove(i + 1);
}
- region[1] = Math.max(nextRegion[1], end);
- hiddenColumns.remove(i + 1);
+ return;
}
- return;
- }
}
/*
* remaining case is that the new range follows everything else
*/
- hiddenColumns.addElement(new int[] { start, end });
+ hiddenColumns.add(new int[] { start, end });
+ } finally
+ {
+ if (!wasAlreadyLocked)
+ {
+ LOCK.writeLock().unlock();
+ }
+ }
}
public boolean isVisible(int column)
{
+ try
+ {
+ LOCK.readLock().lock();
+
if (hiddenColumns != null)
{
for (int[] region : hiddenColumns)
}
return true;
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
}
- /**
- * ColumnSelection
- */
- public HiddenColumns()
+ private ArrayList<int[]> copyHiddenRegionsToArrayList()
{
- }
+ int size = 0;
+ if (hiddenColumns != null)
+ {
+ size = hiddenColumns.size();
+ }
+ ArrayList<int[]> copy = new ArrayList<>(size);
+
+ for (int i = 0, j = size; i < j; i++)
+ {
+ int[] rh;
+ int[] cp;
+ rh = hiddenColumns.get(i);
+ if (rh != null)
+ {
+ cp = new int[rh.length];
+ System.arraycopy(rh, 0, cp, 0, rh.length);
+ copy.add(cp);
+ }
+ }
+ return copy;
+ }
+
/**
- * Copy constructor
+ * Returns a copy of the vector of hidden regions, as an ArrayList. Before
+ * using this method please consider if you really need access to the hidden
+ * regions - a new (or existing!) method on HiddenColumns might be more
+ * appropriate.
*
- * @param copy
+ * @return hidden regions as an ArrayList of [start,end] pairs
*/
- public HiddenColumns(HiddenColumns copy)
+ public ArrayList<int[]> getHiddenColumnsCopy()
{
- if (copy != null)
+ try
{
- if (copy.hiddenColumns != null)
- {
- hiddenColumns = new Vector<int[]>(copy.hiddenColumns.size());
- for (int i = 0, j = copy.hiddenColumns.size(); i < j; i++)
- {
- int[] rh, cp;
- rh = copy.hiddenColumns.elementAt(i);
- if (rh != null)
- {
- cp = new int[rh.length];
- System.arraycopy(rh, 0, cp, 0, rh.length);
- hiddenColumns.addElement(cp);
- }
- }
- }
+ LOCK.readLock().lock();
+ return copyHiddenRegionsToArrayList();
+ } finally
+ {
+ LOCK.readLock().unlock();
}
}
public List<int[]> compensateForEdit(int start, int change,
ColumnSelection sel)
{
- List<int[]> deletedHiddenColumns = null;
-
- if (hiddenColumns != null)
+ try
{
- deletedHiddenColumns = new ArrayList<int[]>();
- int hSize = hiddenColumns.size();
- for (int i = 0; i < hSize; i++)
+ LOCK.writeLock().lock();
+ List<int[]> deletedHiddenColumns = null;
+
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(i);
- if (region[0] > start && start + change > region[1])
+ deletedHiddenColumns = new ArrayList<>();
+ int hSize = hiddenColumns.size();
+ for (int i = 0; i < hSize; i++)
{
- deletedHiddenColumns.add(region);
+ int[] region = hiddenColumns.get(i);
+ if (region[0] > start && start + change > region[1])
+ {
+ deletedHiddenColumns.add(region);
- hiddenColumns.removeElementAt(i);
- i--;
- hSize--;
- continue;
- }
+ hiddenColumns.remove(i);
+ i--;
+ hSize--;
+ continue;
+ }
- if (region[0] > start)
- {
- region[0] -= change;
- region[1] -= change;
- }
+ if (region[0] > start)
+ {
+ region[0] -= change;
+ region[1] -= change;
+ }
+
+ if (region[0] < 0)
+ {
+ region[0] = 0;
+ }
- if (region[0] < 0)
- {
- region[0] = 0;
}
+ this.revealHiddenColumns(0, sel);
}
- this.revealHiddenColumns(0, sel);
+ return deletedHiddenColumns;
+ } finally
+ {
+ LOCK.writeLock().unlock();
}
-
- return deletedHiddenColumns;
}
/**
*/
public void compensateForDelEdits(int start, int change)
{
- if (hiddenColumns != null)
+ try
{
- for (int i = 0; i < hiddenColumns.size(); i++)
+ LOCK.writeLock().lock();
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(i);
- if (region[0] >= start)
- {
- region[0] -= change;
- }
- if (region[1] >= start)
- {
- region[1] -= change;
- }
- if (region[1] < region[0])
+ for (int i = 0; i < hiddenColumns.size(); i++)
{
- hiddenColumns.removeElementAt(i--);
- }
+ int[] region = hiddenColumns.get(i);
+ if (region[0] >= start)
+ {
+ region[0] -= change;
+ }
+ if (region[1] >= start)
+ {
+ region[1] -= change;
+ }
+ if (region[1] < region[0])
+ {
+ hiddenColumns.remove(i--);
+ }
- if (region[0] < 0)
- {
- region[0] = 0;
- }
- if (region[1] < 0)
- {
- region[1] = 0;
+ if (region[0] < 0)
+ {
+ region[0] = 0;
+ }
+ if (region[1] < 0)
+ {
+ region[1] = 0;
+ }
}
}
}
+ finally
+ {
+ LOCK.writeLock().unlock();
+ }
}
/**
*/
public int[] getVisibleContigs(int start, int end)
{
- if (hiddenColumns != null && hiddenColumns.size() > 0)
+ try
{
- List<int[]> visiblecontigs = new ArrayList<int[]>();
- List<int[]> regions = getHiddenRegions();
+ LOCK.readLock().lock();
+ if (hiddenColumns != null && hiddenColumns.size() > 0)
+ {
+ List<int[]> visiblecontigs = new ArrayList<>();
+ List<int[]> regions = getHiddenRegions();
- int vstart = start;
- int[] region;
- int hideStart, hideEnd;
+ int vstart = start;
+ int[] region;
+ int hideStart;
+ int hideEnd;
- for (int j = 0; vstart < end && j < regions.size(); j++)
- {
- region = regions.get(j);
- hideStart = region[0];
- hideEnd = region[1];
+ for (int j = 0; vstart < end && j < regions.size(); j++)
+ {
+ region = regions.get(j);
+ hideStart = region[0];
+ hideEnd = region[1];
+
+ if (hideEnd < vstart)
+ {
+ continue;
+ }
+ if (hideStart > vstart)
+ {
+ visiblecontigs.add(new int[] { vstart, hideStart - 1 });
+ }
+ vstart = hideEnd + 1;
+ }
- if (hideEnd < vstart)
+ if (vstart < end)
{
- continue;
+ visiblecontigs.add(new int[] { vstart, end - 1 });
}
- if (hideStart > vstart)
+ int[] vcontigs = new int[visiblecontigs.size() * 2];
+ for (int i = 0, j = visiblecontigs.size(); i < j; i++)
{
- visiblecontigs.add(new int[] { vstart, hideStart - 1 });
+ int[] vc = visiblecontigs.get(i);
+ visiblecontigs.set(i, null);
+ vcontigs[i * 2] = vc[0];
+ vcontigs[i * 2 + 1] = vc[1];
}
- vstart = hideEnd + 1;
- }
-
- if (vstart < end)
- {
- visiblecontigs.add(new int[] { vstart, end - 1 });
+ visiblecontigs.clear();
+ return vcontigs;
}
- int[] vcontigs = new int[visiblecontigs.size() * 2];
- for (int i = 0, j = visiblecontigs.size(); i < j; i++)
+ else
{
- int[] vc = visiblecontigs.get(i);
- visiblecontigs.set(i, null);
- vcontigs[i * 2] = vc[0];
- vcontigs[i * 2 + 1] = vc[1];
+ return new int[] { start, end - 1 };
}
- visiblecontigs.clear();
- return vcontigs;
}
- else
+ finally
{
- return new int[] { start, end - 1 };
+ LOCK.readLock().unlock();
}
}
public String[] getVisibleSequenceStrings(int start, int end,
SequenceI[] seqs)
{
- int i, iSize = seqs.length;
- String selections[] = new String[iSize];
- if (hiddenColumns != null && hiddenColumns.size() > 0)
+ try
{
- for (i = 0; i < iSize; i++)
+ LOCK.readLock().lock();
+ int iSize = seqs.length;
+ String[] selections = new String[iSize];
+ if (hiddenColumns != null && hiddenColumns.size() > 0)
{
- StringBuffer visibleSeq = new StringBuffer();
- List<int[]> regions = getHiddenRegions();
-
- int blockStart = start, blockEnd = end;
- int[] region;
- int hideStart, hideEnd;
-
- for (int j = 0; j < regions.size(); j++)
+ for (int i = 0; i < iSize; i++)
{
- region = regions.get(j);
- hideStart = region[0];
- hideEnd = region[1];
+ StringBuffer visibleSeq = new StringBuffer();
+ List<int[]> regions = getHiddenRegions();
- if (hideStart < start)
+ int blockStart = start;
+ int blockEnd = end;
+ int[] region;
+ int hideStart;
+ int hideEnd;
+
+ for (int j = 0; j < regions.size(); j++)
{
- continue;
- }
+ region = regions.get(j);
+ hideStart = region[0];
+ hideEnd = region[1];
- blockStart = Math.min(blockStart, hideEnd + 1);
- blockEnd = Math.min(blockEnd, hideStart);
+ if (hideStart < start)
+ {
+ continue;
+ }
- if (blockStart > blockEnd)
- {
- break;
+ blockStart = Math.min(blockStart, hideEnd + 1);
+ blockEnd = Math.min(blockEnd, hideStart);
+
+ if (blockStart > blockEnd)
+ {
+ break;
+ }
+
+ visibleSeq.append(seqs[i].getSequence(blockStart, blockEnd));
+
+ blockStart = hideEnd + 1;
+ blockEnd = end;
}
- visibleSeq.append(seqs[i].getSequence(blockStart, blockEnd));
+ if (end > blockStart)
+ {
+ visibleSeq.append(seqs[i].getSequence(blockStart, end));
+ }
- blockStart = hideEnd + 1;
- blockEnd = end;
+ selections[i] = visibleSeq.toString();
}
-
- if (end > blockStart)
+ }
+ else
+ {
+ for (int i = 0; i < iSize; i++)
{
- visibleSeq.append(seqs[i].getSequence(blockStart, end));
+ selections[i] = seqs[i].getSequenceAsString(start, end);
}
-
- selections[i] = visibleSeq.toString();
}
+
+ return selections;
}
- else
+ finally
{
- for (i = 0; i < iSize; i++)
- {
- selections[i] = seqs[i].getSequenceAsString(start, end);
- }
+ LOCK.readLock().unlock();
}
-
- return selections;
}
/**
*/
public int[] locateVisibleBoundsOfSequence(SequenceI seq)
{
- int fpos = seq.getStart(), lpos = seq.getEnd();
- int start = 0;
-
- if (hiddenColumns == null || hiddenColumns.size() == 0)
+ try
{
- int ifpos = seq.findIndex(fpos) - 1, ilpos = seq.findIndex(lpos) - 1;
- return new int[] { ifpos, ilpos, fpos, lpos, ifpos, ilpos };
- }
+ LOCK.readLock().lock();
+ int fpos = seq.getStart();
+ int lpos = seq.getEnd();
+ int start = 0;
- // Simply walk along the sequence whilst watching for hidden column
- // boundaries
- List<int[]> regions = getHiddenRegions();
- int spos = fpos, lastvispos = -1, rcount = 0, hideStart = seq
- .getLength(), hideEnd = -1;
- int visPrev = 0, visNext = 0, firstP = -1, lastP = -1;
- boolean foundStart = false;
- for (int p = 0, pLen = seq.getLength(); spos <= seq.getEnd()
- && p < pLen; p++)
- {
- if (!Comparison.isGap(seq.getCharAt(p)))
+ if (hiddenColumns == null || hiddenColumns.size() == 0)
{
- // keep track of first/last column
- // containing sequence data regardless of visibility
- if (firstP == -1)
- {
- firstP = p;
- }
- lastP = p;
- // update hidden region start/end
- while (hideEnd < p && rcount < regions.size())
- {
- int[] region = regions.get(rcount++);
- visPrev = visNext;
- visNext += region[0] - visPrev;
- hideStart = region[0];
- hideEnd = region[1];
- }
- if (hideEnd < p)
- {
- hideStart = seq.getLength();
- }
- // update visible boundary for sequence
- if (p < hideStart)
+ int ifpos = seq.findIndex(fpos) - 1;
+ int ilpos = seq.findIndex(lpos) - 1;
+ return new int[] { ifpos, ilpos, fpos, lpos, ifpos, ilpos };
+ }
+
+ // Simply walk along the sequence whilst watching for hidden column
+ // boundaries
+ List<int[]> regions = getHiddenRegions();
+ int spos = fpos;
+ int lastvispos = -1;
+ int rcount = 0;
+ int hideStart = seq.getLength();
+ int hideEnd = -1;
+ int visPrev = 0;
+ int visNext = 0;
+ int firstP = -1;
+ int lastP = -1;
+ boolean foundStart = false;
+ for (int p = 0, pLen = seq.getLength(); spos <= seq.getEnd()
+ && p < pLen; p++)
+ {
+ if (!Comparison.isGap(seq.getCharAt(p)))
{
- if (!foundStart)
+ // keep track of first/last column
+ // containing sequence data regardless of visibility
+ if (firstP == -1)
+ {
+ firstP = p;
+ }
+ lastP = p;
+ // update hidden region start/end
+ while (hideEnd < p && rcount < regions.size())
+ {
+ int[] region = regions.get(rcount++);
+ visPrev = visNext;
+ visNext += region[0] - visPrev;
+ hideStart = region[0];
+ hideEnd = region[1];
+ }
+ if (hideEnd < p)
{
- fpos = spos;
- start = p;
- foundStart = true;
+ hideStart = seq.getLength();
}
- lastvispos = p;
- lpos = spos;
+ // update visible boundary for sequence
+ if (p < hideStart)
+ {
+ if (!foundStart)
+ {
+ fpos = spos;
+ start = p;
+ foundStart = true;
+ }
+ lastvispos = p;
+ lpos = spos;
+ }
+ // look for next sequence position
+ spos++;
}
- // look for next sequence position
- spos++;
}
+ if (foundStart)
+ {
+ return new int[] { findColumnPosition(start),
+ findColumnPosition(lastvispos), fpos, lpos, firstP, lastP };
+ }
+ // otherwise, sequence was completely hidden
+ return new int[] { visPrev, visNext, 0, 0, firstP, lastP };
}
- if (foundStart)
+ finally
{
- return new int[] { findColumnPosition(start),
- findColumnPosition(lastvispos), fpos, lpos, firstP, lastP };
+ LOCK.readLock().unlock();
}
- // otherwise, sequence was completely hidden
- return new int[] { visPrev, visNext, 0, 0, firstP, lastP };
}
/**
public void makeVisibleAnnotation(int start, int end,
AlignmentAnnotation alignmentAnnotation)
{
- if (alignmentAnnotation.annotations == null)
+ try
{
- return;
- }
- if (start == end && end == -1)
- {
- start = 0;
- end = alignmentAnnotation.annotations.length;
- }
- if (hiddenColumns != null && hiddenColumns.size() > 0)
- {
- // then mangle the alignmentAnnotation annotation array
- Vector<Annotation[]> annels = new Vector<Annotation[]>();
- Annotation[] els = null;
- List<int[]> regions = getHiddenRegions();
- int blockStart = start, blockEnd = end;
- int[] region;
- int hideStart, hideEnd, w = 0;
-
- for (int j = 0; j < regions.size(); j++)
+ LOCK.readLock().lock();
+ if (alignmentAnnotation.annotations == null)
{
- region = regions.get(j);
- hideStart = region[0];
- hideEnd = region[1];
+ return;
+ }
+ if (start == end && end == -1)
+ {
+ start = 0;
+ end = alignmentAnnotation.annotations.length;
+ }
+ if (hiddenColumns != null && hiddenColumns.size() > 0)
+ {
+ // then mangle the alignmentAnnotation annotation array
+ Vector<Annotation[]> annels = new Vector<>();
+ Annotation[] els = null;
+ List<int[]> regions = getHiddenRegions();
+ int blockStart = start;
+ int blockEnd = end;
+ int[] region;
+ int hideStart;
+ int hideEnd;
+ int w = 0;
- if (hideStart < start)
+ for (int j = 0; j < regions.size(); j++)
{
- continue;
- }
+ region = regions.get(j);
+ hideStart = region[0];
+ hideEnd = region[1];
- blockStart = Math.min(blockStart, hideEnd + 1);
- blockEnd = Math.min(blockEnd, hideStart);
+ if (hideStart < start)
+ {
+ continue;
+ }
- if (blockStart > blockEnd)
- {
- break;
- }
+ blockStart = Math.min(blockStart, hideEnd + 1);
+ blockEnd = Math.min(blockEnd, hideStart);
- annels.addElement(els = new Annotation[blockEnd - blockStart]);
- System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
- 0, els.length);
- w += els.length;
- blockStart = hideEnd + 1;
- blockEnd = end;
- }
+ if (blockStart > blockEnd)
+ {
+ break;
+ }
- if (end > blockStart)
- {
- annels.addElement(els = new Annotation[end - blockStart + 1]);
- if ((els.length + blockStart) <= alignmentAnnotation.annotations.length)
+ annels.addElement(els = new Annotation[blockEnd - blockStart]);
+ System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
+ 0, els.length);
+ w += els.length;
+ blockStart = hideEnd + 1;
+ blockEnd = end;
+ }
+
+ if (end > blockStart)
{
- // copy just the visible segment of the annotation row
- System.arraycopy(alignmentAnnotation.annotations, blockStart,
- els, 0, els.length);
+ annels.addElement(els = new Annotation[end - blockStart + 1]);
+ if ((els.length
+ + blockStart) <= alignmentAnnotation.annotations.length)
+ {
+ // copy just the visible segment of the annotation row
+ System.arraycopy(alignmentAnnotation.annotations, blockStart,
+ els, 0, els.length);
+ }
+ else
+ {
+ // copy to the end of the annotation row
+ System.arraycopy(alignmentAnnotation.annotations, blockStart,
+ els, 0,
+ (alignmentAnnotation.annotations.length - blockStart));
+ }
+ w += els.length;
}
- else
+ if (w == 0)
{
- // copy to the end of the annotation row
- System.arraycopy(alignmentAnnotation.annotations, blockStart,
- els, 0,
- (alignmentAnnotation.annotations.length - blockStart));
+ return;
}
- w += els.length;
- }
- if (w == 0)
- {
- return;
- }
- alignmentAnnotation.annotations = new Annotation[w];
- w = 0;
+ alignmentAnnotation.annotations = new Annotation[w];
+ w = 0;
- for (Annotation[] chnk : annels)
+ for (Annotation[] chnk : annels)
+ {
+ System.arraycopy(chnk, 0, alignmentAnnotation.annotations, w,
+ chnk.length);
+ w += chnk.length;
+ }
+ }
+ else
{
- System.arraycopy(chnk, 0, alignmentAnnotation.annotations, w,
- chnk.length);
- w += chnk.length;
+ alignmentAnnotation.restrict(start, end);
}
}
- else
+ finally
{
- alignmentAnnotation.restrict(start, end);
+ LOCK.readLock().unlock();
}
}
*/
public boolean hasHiddenColumns()
{
- return hiddenColumns != null && hiddenColumns.size() > 0;
+ try
+ {
+ LOCK.readLock().lock();
+ return hiddenColumns != null && hiddenColumns.size() > 0;
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
}
/**
*/
public boolean hasManyHiddenColumns()
{
- return hiddenColumns != null && hiddenColumns.size() > 1;
+ try
+ {
+ LOCK.readLock().lock();
+ return hiddenColumns != null && hiddenColumns.size() > 1;
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
}
/**
*/
public void hideInsertionsFor(SequenceI sr)
{
- List<int[]> inserts = sr.getInsertions();
- for (int[] r : inserts)
+ try
{
- hideColumns(r[0], r[1]);
+ LOCK.writeLock().lock();
+ List<int[]> inserts = sr.getInsertions();
+ for (int[] r : inserts)
+ {
+ hideColumns(r[0], r[1]);
+ }
+ } finally
+ {
+ LOCK.writeLock().unlock();
}
}
*/
public void revealAllHiddenColumns(ColumnSelection sel)
{
- if (hiddenColumns != null)
+ try
{
- for (int i = 0; i < hiddenColumns.size(); i++)
+ LOCK.writeLock().lock();
+ if (hiddenColumns != null)
{
- int[] region = hiddenColumns.elementAt(i);
- for (int j = region[0]; j < region[1] + 1; j++)
+ for (int i = 0; i < hiddenColumns.size(); i++)
{
- sel.addElement(j);
+ int[] region = hiddenColumns.get(i);
+ for (int j = region[0]; j < region[1] + 1; j++)
+ {
+ sel.addElement(j);
+ }
}
}
- }
- hiddenColumns = null;
+ hiddenColumns = null;
+ }
+ finally
+ {
+ LOCK.writeLock().unlock();
+ }
}
/**
*/
public void revealHiddenColumns(int start, ColumnSelection sel)
{
- for (int i = 0; i < hiddenColumns.size(); i++)
+ try
{
- int[] region = hiddenColumns.elementAt(i);
- if (start == region[0])
+ LOCK.writeLock().lock();
+ for (int i = 0; i < hiddenColumns.size(); i++)
{
- for (int j = region[0]; j < region[1] + 1; j++)
+ int[] region = hiddenColumns.get(i);
+ if (start == region[0])
{
- sel.addElement(j);
- }
+ for (int j = region[0]; j < region[1] + 1; j++)
+ {
+ sel.addElement(j);
+ }
- hiddenColumns.removeElement(region);
- break;
+ hiddenColumns.remove(region);
+ break;
+ }
+ }
+ if (hiddenColumns.size() == 0)
+ {
+ hiddenColumns = null;
}
}
- if (hiddenColumns.size() == 0)
+ finally
{
- hiddenColumns = null;
+ LOCK.writeLock().unlock();
}
}
* @param intervals
* @return
*/
- private boolean pruneIntervalVector(final List<int[]> shifts,
- Vector<int[]> intervals)
+ private boolean pruneIntervalList(final List<int[]> shifts,
+ ArrayList<int[]> intervals)
{
boolean pruned = false;
- int i = 0, j = intervals.size() - 1, s = 0, t = shifts.size() - 1;
- int hr[] = intervals.elementAt(i);
- int sr[] = shifts.get(s);
+ int i = 0;
+ int j = intervals.size() - 1;
+ int s = 0;
+ int t = shifts.size() - 1;
+ int[] hr = intervals.get(i);
+ int[] sr = shifts.get(s);
while (i <= j && s <= t)
{
boolean trailinghn = hr[1] >= sr[0];
{
if (i < j)
{
- hr = intervals.elementAt(++i);
+ hr = intervals.get(++i);
}
else
{
{
if (trailinghc)
{ // deleted hidden region.
- intervals.removeElementAt(i);
+ intervals.remove(i);
pruned = true;
j--;
if (i <= j)
{
- hr = intervals.elementAt(i);
+ hr = intervals.get(i);
}
continue;
}
*/
public void pruneDeletions(List<int[]> shifts)
{
- // delete any intervals intersecting.
- if (hiddenColumns != null)
+ try
{
- pruneIntervalVector(shifts, hiddenColumns);
- if (hiddenColumns != null && hiddenColumns.size() == 0)
+ LOCK.writeLock().lock();
+ // delete any intervals intersecting.
+ if (hiddenColumns != null)
{
- hiddenColumns = null;
+ pruneIntervalList(shifts, hiddenColumns);
+ if (hiddenColumns != null && hiddenColumns.size() == 0)
+ {
+ hiddenColumns = null;
+ }
}
}
+ finally
+ {
+ LOCK.writeLock().unlock();
+ }
}
/**
// recover mapping between sequence's non-gap positions and positions
// mapping to view.
pruneDeletions(ShiftList.parseMap(origseq.gapMap()));
- int[] viscontigs = al.getHiddenColumns().getVisibleContigs(0,
- profileseq.getLength());
+ int[] viscontigs = getVisibleContigs(0, profileseq.getLength());
int spos = 0;
int offset = 0;
@Override
public int hashCode()
{
- int hashCode = 1;
- if (hiddenColumns != null)
+ try
{
- for (int[] hidden : hiddenColumns)
+ LOCK.readLock().lock();
+ int hashCode = 1;
+ if (hiddenColumns != null)
{
- hashCode = 31 * hashCode + hidden[0];
- hashCode = 31 * hashCode + hidden[1];
+ for (int[] hidden : hiddenColumns)
+ {
+ hashCode = 31 * hashCode + hidden[0];
+ hashCode = 31 * hashCode + hidden[1];
+ }
}
+ return hashCode;
+ }
+ finally
+ {
+ LOCK.readLock().unlock();
}
- return hashCode;
}
/**
*/
public void hideMarkedBits(BitSet inserts)
{
- for (int firstSet = inserts.nextSetBit(0), lastSet = 0; firstSet >= 0; firstSet = inserts
- .nextSetBit(lastSet))
+ try
{
- lastSet = inserts.nextClearBit(firstSet);
- hideColumns(firstSet, lastSet - 1);
+ LOCK.writeLock().lock();
+ for (int firstSet = inserts
+ .nextSetBit(0), lastSet = 0; firstSet >= 0; firstSet = inserts
+ .nextSetBit(lastSet))
+ {
+ lastSet = inserts.nextClearBit(firstSet);
+ hideColumns(firstSet, lastSet - 1);
+ }
+ } finally
+ {
+ LOCK.writeLock().unlock();
}
}
*/
public void markHiddenRegions(BitSet inserts)
{
- if (hiddenColumns == null)
+ try
+ {
+ LOCK.readLock().lock();
+ if (hiddenColumns == null)
+ {
+ return;
+ }
+ for (int[] range : hiddenColumns)
+ {
+ inserts.set(range[0], range[1] + 1);
+ }
+ }
+ finally
{
- return;
+ LOCK.readLock().unlock();
}
- for (int[] range : hiddenColumns)
+ }
+
+ /**
+ * Calculate the visible start and end index of an alignment.
+ *
+ * @param width
+ * full alignment width
+ * @return integer array where: int[0] = startIndex, and int[1] = endIndex
+ */
+ public int[] getVisibleStartAndEndIndex(int width)
+ {
+ try
+ {
+ LOCK.readLock().lock();
+ int[] alignmentStartEnd = new int[] { 0, width - 1 };
+ int startPos = alignmentStartEnd[0];
+ int endPos = alignmentStartEnd[1];
+
+ int[] lowestRange = new int[] { -1, -1 };
+ int[] higestRange = new int[] { -1, -1 };
+
+ if (hiddenColumns == null)
+ {
+ return new int[] { startPos, endPos };
+ }
+
+ for (int[] hiddenCol : hiddenColumns)
+ {
+ lowestRange = (hiddenCol[0] <= startPos) ? hiddenCol : lowestRange;
+ higestRange = (hiddenCol[1] >= endPos) ? hiddenCol : higestRange;
+ }
+
+ if (lowestRange[0] == -1 && lowestRange[1] == -1)
+ {
+ startPos = alignmentStartEnd[0];
+ }
+ else
+ {
+ startPos = lowestRange[1] + 1;
+ }
+
+ if (higestRange[0] == -1 && higestRange[1] == -1)
+ {
+ endPos = alignmentStartEnd[1];
+ }
+ else
+ {
+ endPos = higestRange[0] - 1;
+ }
+ return new int[] { startPos, endPos };
+ } finally
+ {
+ LOCK.readLock().unlock();
+ }
+
+ }
+
+ /**
+ * Finds the hidden region (if any) which starts or ends at res
+ *
+ * @param res
+ * visible residue position, unadjusted for hidden columns
+ * @return region as [start,end] or null if no matching region is found
+ */
+ public int[] getRegionWithEdgeAtRes(int res)
+ {
+ try
+ {
+ LOCK.readLock().lock();
+ int adjres = adjustForHiddenColumns(res);
+
+ int[] reveal = null;
+ if (hiddenColumns != null)
+ {
+ for (int[] region : hiddenColumns)
+ {
+ if (adjres + 1 == region[0] || adjres - 1 == region[1])
+ {
+ reveal = region;
+ break;
+ }
+ }
+ }
+ return reveal;
+ } finally
{
- inserts.set(range[0], range[1] + 1);
+ LOCK.readLock().unlock();
}
}
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
* A copy constructor that allows the value of final fields to be 'modified'
*
* @param sf
+ * @param newType
* @param newBegin
* @param newEnd
* @param newGroup
* @param newScore
*/
- public SequenceFeature(SequenceFeature sf, int newBegin, int newEnd,
- String newGroup, float newScore)
+ public SequenceFeature(SequenceFeature sf, String newType, int newBegin,
+ int newEnd, String newGroup, float newScore)
{
- this(sf.getType(), sf.getDescription(), newBegin, newEnd, newScore,
+ this(newType, sf.getDescription(), newBegin, newEnd, newScore,
newGroup);
if (sf.otherDetails != null)
}
/**
+ * A copy constructor that allows the value of final fields to be 'modified'
+ *
+ * @param sf
+ * @param newBegin
+ * @param newEnd
+ * @param newGroup
+ * @param newScore
+ */
+ public SequenceFeature(SequenceFeature sf, int newBegin, int newEnd,
+ String newGroup, float newScore)
+ {
+ this(sf, sf.getType(), newBegin, newEnd, newGroup, newScore);
+ }
+
+ /**
* Two features are considered equal if they have the same type, group,
* description, start, end, phase, strand, and (if present) 'Name', ID' and
* 'Parent' attributes.
colourText = seqsel.colourText;
startRes = seqsel.startRes;
endRes = seqsel.endRes;
- cs = new ResidueShader(seqsel.getColourScheme());
+ cs = new ResidueShader((ResidueShader) seqsel.cs);
if (seqsel.description != null)
{
description = new String(seqsel.description);
last = lastcol;
current = firstcol;
next = firstcol;
- hidden = hiddenCols.getHiddenRegions();
+ hidden = hiddenCols.getHiddenColumnsCopy();
lasthiddenregion = -1;
if (hidden != null)
public AlignViewControllerI avc;
- List<AlignmentPanel> alignPanels = new ArrayList<AlignmentPanel>();
+ List<AlignmentPanel> alignPanels = new ArrayList<>();
/**
* Last format used to load or save alignments in this window
addKeyListener();
- final List<AlignmentPanel> selviews = new ArrayList<AlignmentPanel>();
- final List<AlignmentPanel> origview = new ArrayList<AlignmentPanel>();
+ final List<AlignmentPanel> selviews = new ArrayList<>();
+ final List<AlignmentPanel> origview = new ArrayList<>();
final String menuLabel = MessageManager
.getString("label.copy_format_from");
ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
origview.clear();
origview.add(alignPanel);
// make an array of all alignment panels except for this one
- List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>(
+ List<AlignmentPanel> aps = new ArrayList<>(
Arrays.asList(Desktop.getAlignmentPanels(null)));
aps.remove(AlignFrame.this.alignPanel);
return aps.toArray(new AlignmentPanel[aps.size()]);
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;
}
}
{
alignmentToExport = viewport.getAlignment();
}
- alignmentStartEnd = alignmentToExport
- .getVisibleStartAndEndIndex(viewport.getAlignment()
- .getHiddenColumns()
- .getHiddenRegions());
+ alignmentStartEnd = viewport.getAlignment().getHiddenColumns()
+ .getVisibleStartAndEndIndex(alignmentToExport.getWidth());
AlignmentExportData ed = new AlignmentExportData(alignmentToExport,
omitHidden, alignmentStartEnd, settings);
return ed;
synchronized void slideSequences(boolean right, int size)
{
- List<SequenceI> sg = new ArrayList<SequenceI>();
+ List<SequenceI> sg = new ArrayList<>();
if (viewport.cursorMode)
{
sg.add(viewport.getAlignment().getSequenceAt(
return;
}
- List<SequenceI> invertGroup = new ArrayList<SequenceI>();
+ List<SequenceI> invertGroup = new ArrayList<>();
for (SequenceI seq : viewport.getAlignment().getSequences())
{
ArrayList<int[]> hiddenColumns = null;
if (viewport.hasHiddenColumns())
{
- hiddenColumns = new ArrayList<int[]>();
- int hiddenOffset = viewport.getSelectionGroup().getStartRes(), hiddenCutoff = viewport
- .getSelectionGroup().getEndRes();
- for (int[] region : viewport.getAlignment().getHiddenColumns()
- .getHiddenRegions())
+ hiddenColumns = new ArrayList<>();
+ int hiddenOffset = viewport.getSelectionGroup().getStartRes();
+ int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
+ ArrayList<int[]> hiddenRegions = viewport.getAlignment()
+ .getHiddenColumns().getHiddenColumnsCopy();
+ for (int[] region : hiddenRegions)
{
if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff)
{
}
int alwidth = 0;
- ArrayList<Integer> newGraphGroups = new ArrayList<Integer>();
+ ArrayList<Integer> newGraphGroups = new ArrayList<>();
int fgroup = -1;
if (newAlignment)
viewport.setSelectionGroup(null);
viewport.getColumnSelection().clear();
viewport.setSelectionGroup(null);
- alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(null);
alignPanel.getIdPanel().getIdCanvas().searchResults = null;
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
*/
protected List<String> getExistingViewNames(List<Component> comps)
{
- List<String> existingNames = new ArrayList<String>();
+ List<String> existingNames = new ArrayList<>();
for (Component comp : comps)
{
if (comp instanceof AlignmentPanel)
{
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);
};
});
List<Component> comps = PaintRefresher.components.get(viewport
.getSequenceSetId());
- List<TreePanel> treePanels = new ArrayList<TreePanel>();
+ List<TreePanel> treePanels = new ArrayList<>();
for (Component comp : comps)
{
if (comp instanceof TreePanel)
@Override
public void run()
{
- final List<JMenuItem> legacyItems = new ArrayList<JMenuItem>();
+ final List<JMenuItem> legacyItems = new ArrayList<>();
try
{
// System.err.println("Building ws menu again "
// TODO: group services by location as well as function and/or
// introduce
// object broker mechanism.
- final Vector<JMenu> wsmenu = new Vector<JMenu>();
+ final Vector<JMenu> wsmenu = new Vector<>();
final IProgressIndicator af = me;
/*
// Java's Transferable for native dnd
evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
Transferable t = evt.getTransferable();
- List<String> files = new ArrayList<String>();
- List<DataSourceType> protocols = new ArrayList<DataSourceType>();
+ List<String> files = new ArrayList<>();
+ List<DataSourceType> protocols = new ArrayList<>();
try
{
/**
* Object[] { String,SequenceI}
*/
- ArrayList<Object[]> filesmatched = new ArrayList<Object[]>();
- ArrayList<String> filesnotmatched = new ArrayList<String>();
+ ArrayList<Object[]> filesmatched = new ArrayList<>();
+ ArrayList<String> filesnotmatched = new ArrayList<>();
for (int i = 0; i < files.size(); i++)
{
String file = files.get(i).toString();
{
return;
}
- List<SequenceI> cdnaSeqs = new ArrayList<SequenceI>();
+ List<SequenceI> cdnaSeqs = new ArrayList<>();
for (SequenceI aaSeq : alignment.getSequences())
{
for (AlignedCodonFrame acf : mappings)
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
-import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.renderer.ResidueShader;
}
}
- /**
- * get the consensus sequence as displayed under the PID consensus annotation
- * row.
- *
- * @return consensus sequence as a new sequence object
- */
- public SequenceI getConsensusSeq()
- {
- if (consensus == null)
- {
- updateConsensus(null);
- }
- if (consensus == null)
- {
- return null;
- }
- StringBuffer seqs = new StringBuffer();
- for (int i = 0; i < consensus.annotations.length; i++)
- {
- if (consensus.annotations[i] != null)
- {
- if (consensus.annotations[i].description.charAt(0) == '[')
- {
- seqs.append(consensus.annotations[i].description.charAt(1));
- }
- else
- {
- seqs.append(consensus.annotations[i].displayCharacter);
- }
- }
- }
-
- SequenceI sq = new Sequence("Consensus", seqs.toString());
- sq.setDescription("Percentage Identity Consensus "
- + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
- return sq;
- }
-
boolean validCharWidth;
/**
*/
public void highlightSearchResults(SearchResultsI results)
{
- scrollToPosition(results);
- getSeqPanel().seqCanvas.highlightSearchResults(results);
- }
+ boolean scrolled = scrollToPosition(results, 0, true, false);
- /**
- * Scroll the view to show the position of the highlighted region in results
- * (if any) and redraw the overview
- *
- * @param results
- */
- public boolean scrollToPosition(SearchResultsI results)
- {
- return scrollToPosition(results, 0, true, false);
+ boolean noFastPaint = scrolled && av.getWrapAlignment();
+
+ getSeqPanel().seqCanvas.highlightSearchResults(results, noFastPaint);
}
/**
}
/**
- * Scroll the view to show the position of the highlighted region in results
- * (if any)
+ * Scrolls the view (if necessary) to show the position of the first
+ * highlighted region in results (if any). Answers true if the view was
+ * scrolled, or false if no matched region was found, or it is already
+ * visible.
*
* @param results
* @param verticalOffset
* - when set, the overview will be recalculated (takes longer)
* @param centre
* if true, try to centre the search results horizontally in the view
- * @return false if results were not found
+ * @return
*/
- public boolean scrollToPosition(SearchResultsI results,
+ protected boolean scrollToPosition(SearchResultsI results,
int verticalOffset, boolean redrawOverview, boolean centre)
{
int startv, endv, starts, ends;
- // TODO: properly locate search results in view when large numbers of hidden
- // columns exist before highlighted region
- // do we need to scroll the panel?
- // TODO: tons of nullpointerexceptions raised here.
- if (results != null && results.getSize() > 0 && av != null
- && av.getAlignment() != null)
- {
- int seqIndex = av.getAlignment().findIndex(results);
- if (seqIndex == -1)
- {
- return false;
- }
- SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
- int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
- if (r == null)
- {
- return false;
- }
- int start = r[0];
- int end = r[1];
+ if (results == null || results.isEmpty() || av == null
+ || av.getAlignment() == null)
+ {
+ return false;
+ }
+ int seqIndex = av.getAlignment().findIndex(results);
+ if (seqIndex == -1)
+ {
+ return false;
+ }
+ SequenceI seq = av.getAlignment().getSequenceAt(seqIndex);
- /*
- * To centre results, scroll to positions half the visible width
- * left/right of the start/end positions
- */
- if (centre)
- {
- int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2
- - 1;
- start = Math.max(start - offset, 0);
- end = end + offset - 1;
- }
- if (start < 0)
- {
- return false;
- }
- if (end == seq.getEnd())
- {
- return false;
- }
- if (av.hasHiddenColumns())
+ int[] r = results.getResults(seq, 0, av.getAlignment().getWidth());
+ if (r == null)
+ {
+ return false;
+ }
+ int start = r[0];
+ int end = r[1];
+
+ /*
+ * To centre results, scroll to positions half the visible width
+ * left/right of the start/end positions
+ */
+ if (centre)
+ {
+ int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - 1;
+ start = Math.max(start - offset, 0);
+ end = end + offset - 1;
+ }
+ if (start < 0)
+ {
+ return false;
+ }
+ if (end == seq.getEnd())
+ {
+ return false;
+ }
+
+ if (av.hasHiddenColumns())
+ {
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ start = hidden.findColumnPosition(start);
+ end = hidden.findColumnPosition(end);
+ if (start == end)
{
- HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- start = hidden.findColumnPosition(start);
- end = hidden.findColumnPosition(end);
- if (start == end)
+ if (!hidden.isVisible(r[0]))
{
- if (!hidden.isVisible(r[0]))
- {
- // don't scroll - position isn't visible
- return false;
- }
+ // don't scroll - position isn't visible
+ return false;
}
}
+ }
- /*
- * allow for offset of target sequence (actually scroll to one above it)
- */
- seqIndex = Math.max(0, seqIndex - verticalOffset);
+ /*
+ * allow for offset of target sequence (actually scroll to one above it)
+ */
+ seqIndex = Math.max(0, seqIndex - verticalOffset);
+ boolean scrollNeeded = true;
- if (!av.getWrapAlignment())
+ if (!av.getWrapAlignment())
+ {
+ if ((startv = vpRanges.getStartRes()) >= start)
{
- if ((startv = vpRanges.getStartRes()) >= start)
- {
- /*
- * Scroll left to make start of search results visible
- */
- setScrollValues(start, seqIndex);
- }
- else if ((endv = vpRanges.getEndRes()) <= end)
- {
- /*
- * Scroll right to make end of search results visible
- */
- setScrollValues(startv + end - endv, seqIndex);
- }
- else if ((starts = vpRanges.getStartSeq()) > seqIndex)
- {
- /*
- * Scroll up to make start of search results visible
- */
- setScrollValues(vpRanges.getStartRes(), seqIndex);
- }
- else if ((ends = vpRanges.getEndSeq()) <= seqIndex)
- {
- /*
- * Scroll down to make end of search results visible
- */
- setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends
- + 1);
- }
/*
- * Else results are already visible - no need to scroll
+ * Scroll left to make start of search results visible
*/
+ setScrollValues(start, seqIndex);
}
- else
+ else if ((endv = vpRanges.getEndRes()) <= end)
+ {
+ /*
+ * Scroll right to make end of search results visible
+ */
+ setScrollValues(startv + end - endv, seqIndex);
+ }
+ else if ((starts = vpRanges.getStartSeq()) > seqIndex)
+ {
+ /*
+ * Scroll up to make start of search results visible
+ */
+ setScrollValues(vpRanges.getStartRes(), seqIndex);
+ }
+ else if ((ends = vpRanges.getEndSeq()) <= seqIndex)
{
- vpRanges.scrollToWrappedVisible(start);
+ /*
+ * Scroll down to make end of search results visible
+ */
+ setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends
+ + 1);
}
+ /*
+ * Else results are already visible - no need to scroll
+ */
+ scrollNeeded = false;
+ }
+ else
+ {
+ scrollNeeded = vpRanges.scrollToWrappedVisible(start);
}
paintAlignment(redrawOverview);
- return true;
+
+ return scrollNeeded;
}
/**
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);
}
/**
* @param verticalOffset
* the number of visible sequences to show above the mapped region
*/
- public void scrollToCentre(SearchResultsI sr, int verticalOffset)
+ protected void scrollToCentre(SearchResultsI sr, int verticalOffset)
{
/*
* To avoid jumpy vertical scrolling (if some sequences are gapped or not
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
-import java.util.Iterator;
+import java.util.ArrayList;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
HiddenColumns oldHidden = av
.getAnnotationColumnSelectionState()
.getOldHiddenColumns();
- if (oldHidden != null && oldHidden.getHiddenRegions() != null
- && !oldHidden.getHiddenRegions().isEmpty())
+ if (oldHidden != null)
{
- for (Iterator<int[]> itr = oldHidden.getHiddenRegions()
- .iterator(); itr.hasNext();)
+ ArrayList<int[]> regions = oldHidden.getHiddenColumnsCopy();
+ for (int[] positions : regions)
{
- int positions[] = itr.next();
av.hideColumns(positions[0], positions[1]);
}
}
+ // TODO not clear why we need to hide all the columns (above) if we are
+ // going to copy the hidden columns over wholesale anyway
av.getAlignment().setHiddenColumns(oldHidden);
}
av.sendSelection();
private static final String FILTER_BY_ANN_CACHE_KEY = "CACHE.SELECT_FILTER_BY_ANNOT";
- public JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<String>(
+ public JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<>(
FILTER_BY_ANN_CACHE_KEY);
public SearchPanel(AnnotationColumnChooser aColChooser)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
import java.util.regex.Pattern;
import javax.swing.JCheckBoxMenuItem;
}
int[] alignmentStartEnd = new int[] { 0, ds.getWidth() - 1 };
- List<int[]> hiddenCols = av.getAlignment().getHiddenColumns()
- .getHiddenRegions();
- if (hiddenCols != null)
+ if (av.hasHiddenColumns())
{
- alignmentStartEnd = av.getAlignment().getVisibleStartAndEndIndex(
- hiddenCols);
+ alignmentStartEnd = av.getAlignment().getHiddenColumns()
+ .getVisibleStartAndEndIndex(av.getAlignment().getWidth());
}
+
String output = new FormatAdapter().formatSequences(FileFormat.Fasta,
seqs, omitHidden, alignmentStartEnd);
.setContents(new StringSelection(output), Desktop.instance);
ArrayList<int[]> hiddenColumns = null;
+
if (av.hasHiddenColumns())
{
- hiddenColumns = new ArrayList<int[]>();
- for (int[] region : av.getAlignment().getHiddenColumns()
- .getHiddenRegions())
- {
- hiddenColumns.add(new int[] { region[0], region[1] });
- }
+ hiddenColumns = av.getAlignment().getHiddenColumns()
+ .getHiddenColumnsCopy();
}
Desktop.jalviewClipboard = new Object[] { seqs, ds, // what is the dataset
import jalview.util.Comparison;
import jalview.util.MessageManager;
import jalview.viewmodel.ViewportListenerI;
+import jalview.viewmodel.ViewportRanges;
import java.awt.AlphaComposite;
import java.awt.Color;
* the selection list (read-only view) is in selection order, not
* column order; make a copy so we can sort it
*/
- List<Integer> selected = new ArrayList<Integer>(viscols.getSelected());
+ List<Integer> selected = new ArrayList<>(viscols.getSelected());
Collections.sort(selected);
for (int index : selected)
{
repaint();
return;
}
+
+ int sr = av.getRanges().getStartRes();
+ int er = av.getRanges().getEndRes() + 1;
+ int transX = 0;
+
long stime = System.currentTimeMillis();
gg.copyArea(0, 0, imgWidth, getHeight(),
-horizontal * av.getCharWidth(), 0);
long mtime = System.currentTimeMillis();
- int sr = av.getRanges().getStartRes();
- int er = av.getRanges().getEndRes() + 1;
- int transX = 0;
if (horizontal > 0) // scrollbar pulled right, image to the left
{
public void propertyChange(PropertyChangeEvent evt)
{
// Respond to viewport range changes (e.g. alignment panel was scrolled)
- if (evt.getPropertyName().equals("startres")
- || evt.getPropertyName().equals("endres"))
+ // 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.STARTRES))
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
// 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;
highlight.addResult(sequences.get(0), sf.getBegin(),
sf.getEnd());
- alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(highlight);
+ alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(
+ highlight, false);
}
FeatureColourI col = getFeatureStyle(name.getText());
* (to ensure integrity of SequenceFeatures data store)
*/
sequences.get(0).deleteFeature(sf);
- SequenceFeature newSf = new SequenceFeature(sf, newBegin, newEnd,
- enteredGroup, sf.getScore());
+ SequenceFeature newSf = new SequenceFeature(sf, enteredType,
+ newBegin, newEnd, enteredGroup, sf.getScore());
sf.setDescription(enteredDescription);
ffile.parseDescriptionHTML(newSf, false);
// amend features dialog only updates one sequence at a time
*/
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)
- if (evt.getPropertyName().equals("startseq")
- || evt.getPropertyName().equals("endseq"))
+ 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);
}
/**
* Map of reconstructed AlignFrame objects that appear to have come from
* SplitFrame objects (have a dna/protein complement view).
*/
- private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<Viewport, AlignFrame>();
+ private Map<Viewport, AlignFrame> splitFrameCandidates = new HashMap<>();
/*
* Map from displayed rna structure models to their saved session state jar
* entry names
*/
- private Map<RnaModel, String> rnaSessions = new HashMap<RnaModel, String>();
+ private Map<RnaModel, String> rnaSessions = new HashMap<>();
/**
* create/return unique hash string for sq
{
if (seqsToIds == null)
{
- seqsToIds = new IdentityHashMap<SequenceI, String>();
+ seqsToIds = new IdentityHashMap<>();
}
if (seqRefIds == null)
{
- seqRefIds = new HashMap<String, SequenceI>();
+ seqRefIds = new HashMap<>();
}
if (incompleteSeqs == null)
{
- incompleteSeqs = new HashMap<String, SequenceI>();
+ incompleteSeqs = new HashMap<>();
}
if (frefedSequence == null)
{
- frefedSequence = new ArrayList<SeqFref>();
+ frefedSequence = new ArrayList<>();
}
}
* This maintains a map of viewports, the key being the seqSetId. Important to
* set historyItem and redoList for multiple views
*/
- Map<String, AlignViewport> viewportsAdded = new HashMap<String, AlignViewport>();
+ Map<String, AlignViewport> viewportsAdded = new HashMap<>();
- Map<String, AlignmentAnnotation> annotationIds = new HashMap<String, AlignmentAnnotation>();
+ Map<String, AlignmentAnnotation> annotationIds = new HashMap<>();
String uniqueSetSuffix = "";
*/
private void saveAllFrames(List<AlignFrame> frames, JarOutputStream jout)
{
- Hashtable<String, AlignFrame> dsses = new Hashtable<String, AlignFrame>();
+ Hashtable<String, AlignFrame> dsses = new Hashtable<>();
/*
* ensure cached data is clear before starting
// NOTE UTF-8 MUST BE USED FOR WRITING UNICODE CHARS
// //////////////////////////////////////////////////
- List<String> shortNames = new ArrayList<String>();
- List<String> viewIds = new ArrayList<String>();
+ List<String> shortNames = new ArrayList<>();
+ List<String> viewIds = new ArrayList<>();
// REVERSE ORDER
for (int i = frames.size() - 1; i > -1; i--)
{
FileOutputStream fos = new FileOutputStream(jarFile);
JarOutputStream jout = new JarOutputStream(fos);
- List<AlignFrame> frames = new ArrayList<AlignFrame>();
+ List<AlignFrame> frames = new ArrayList<>();
// resolve splitframes
if (af.getViewport().getCodingComplement() != null)
{
if (viewIds == null)
{
- viewIds = new ArrayList<String>();
+ viewIds = new ArrayList<>();
}
initSeqRefs();
- List<UserColourScheme> userColours = new ArrayList<UserColourScheme>();
+ List<UserColourScheme> userColours = new ArrayList<>();
AlignViewport av = ap.av;
ViewportRanges vpRanges = av.getRanges();
}
JSeq jseq;
- Set<String> calcIdSet = new HashSet<String>();
+ Set<String> calcIdSet = new HashSet<>();
// record the set of vamsas sequence XML POJO we create.
- HashMap<String, Sequence> vamsasSetIds = new HashMap<String, Sequence>();
+ HashMap<String, Sequence> vamsasSetIds = new HashMap<>();
// SAVE SEQUENCES
for (final SequenceI jds : rjal.getSequences())
{
pdb.setFile(matchedFile); // entry.getFile());
if (pdbfiles == null)
{
- pdbfiles = new ArrayList<String>();
+ pdbfiles = new ArrayList<>();
}
if (!pdbfiles.contains(pdbId))
/**
* store forward refs from an annotationRow to any groups
*/
- IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<SequenceGroup, String>();
+ IdentityHashMap<SequenceGroup, String> groupRefs = new IdentityHashMap<>();
if (storeDS)
{
for (SequenceI sq : jal.getSequences())
.getFeatureRenderer().getRenderOrder()
.toArray(new String[0]);
- Vector<String> settingsAdded = new Vector<String>();
+ Vector<String> settingsAdded = new Vector<>();
if (renderOrder != null)
{
for (String featureType : renderOrder)
// is groups actually supposed to be a map here ?
Iterator<String> en = ap.getSeqPanel().seqCanvas
.getFeatureRenderer().getFeatureGroups().iterator();
- Vector<String> groupsAdded = new Vector<String>();
+ Vector<String> groupsAdded = new Vector<>();
while (en.hasNext())
{
String grp = en.next();
{
jalview.datamodel.HiddenColumns hidden = av.getAlignment()
.getHiddenColumns();
- if (hidden == null || hidden.getHiddenRegions() == null)
+ if (hidden == null)
{
warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
}
else
{
- for (int c = 0; c < hidden.getHiddenRegions()
- .size(); c++)
+ ArrayList<int[]> hiddenRegions = hidden
+ .getHiddenColumnsCopy();
+ for (int[] region : hiddenRegions)
{
- int[] region = hidden.getHiddenRegions()
- .get(c);
HiddenColumns hc = new HiddenColumns();
hc.setStart(region[0]);
hc.setEnd(region[1]);
try
{
// create list to store references for any new Jmol viewers created
- newStructureViewers = new Vector<JalviewStructureDisplayI>();
+ newStructureViewers = new Vector<>();
// UNMARSHALLER SEEMS TO CLOSE JARINPUTSTREAM, MOST ANNOYING
// Workaround is to make sure caller implements the JarInputStreamProvider
// interface
initSeqRefs();
}
AlignFrame af = null, _af = null;
- IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<AlignmentI, AlignmentI>();
- Map<String, AlignFrame> gatherToThisFrame = new HashMap<String, AlignFrame>();
+ IdentityHashMap<AlignmentI, AlignmentI> importedDatasets = new IdentityHashMap<>();
+ Map<String, AlignFrame> gatherToThisFrame = new HashMap<>();
final String file = jprovider.getFilename();
try
{
*/
protected void restoreSplitFrames()
{
- List<SplitFrame> gatherTo = new ArrayList<SplitFrame>();
- List<AlignFrame> addedToSplitFrames = new ArrayList<AlignFrame>();
- Map<String, AlignFrame> dna = new HashMap<String, AlignFrame>();
+ List<SplitFrame> gatherTo = new ArrayList<>();
+ List<AlignFrame> addedToSplitFrames = new ArrayList<>();
+ Map<String, AlignFrame> dna = new HashMap<>();
/*
* Identify the DNA alignments
errorMessage = null;
}
- Map<String, String> alreadyLoadedPDB = new HashMap<String, String>();
+ Map<String, String> alreadyLoadedPDB = new HashMap<>();
/**
* when set, local views will be updated from view stored in JalviewXML
List<SequenceI> hiddenSeqs = null;
- List<SequenceI> tmpseqs = new ArrayList<SequenceI>();
+ List<SequenceI> tmpseqs = new ArrayList<>();
boolean multipleView = false;
SequenceI referenceseqForView = null;
{
if (hiddenSeqs == null)
{
- hiddenSeqs = new ArrayList<SequenceI>();
+ hiddenSeqs = new ArrayList<>();
}
hiddenSeqs.add(tmpSeq);
// ////////////////////////////////
// LOAD ANNOTATIONS
- List<JvAnnotRow> autoAlan = new ArrayList<JvAnnotRow>();
+ List<JvAnnotRow> autoAlan = new ArrayList<>();
/*
* store any annotations which forward reference a group's ID
*/
- Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<String, List<AlignmentAnnotation>>();
+ Map<String, List<AlignmentAnnotation>> groupAnnotRefs = new Hashtable<>();
if (vamsasSet.getAnnotationCount() > 0)
{
.get(an[i].getGroupRef());
if (aal == null)
{
- aal = new ArrayList<jalview.datamodel.AlignmentAnnotation>();
+ aal = new ArrayList<>();
groupAnnotRefs.put(an[i].getGroupRef(), aal);
}
aal.add(jaa);
}
int pidThreshold = jGroup.getPidThreshold();
- Vector<SequenceI> seqs = new Vector<SequenceI>();
+ Vector<SequenceI> seqs = new Vector<>();
for (int s = 0; s < jGroup.getSeqCount(); s++)
{
* Run through all PDB ids on the alignment, and collect mappings between
* distinct view ids and all sequences referring to that view.
*/
- Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<String, StructureViewerModel>();
+ Map<String, StructureViewerModel> structureViewers = new LinkedHashMap<>();
for (int i = 0; i < jseqs.length; i++)
{
Set<Entry<File, StructureData>> fileData = data.getFileData()
.entrySet();
- List<PDBEntry> pdbs = new ArrayList<PDBEntry>();
- List<SequenceI[]> allseqs = new ArrayList<SequenceI[]>();
+ List<PDBEntry> pdbs = new ArrayList<>();
+ List<SequenceI[]> allseqs = new ArrayList<>();
for (Entry<File, StructureData> pdb : fileData)
{
String filePath = pdb.getValue().getFilePath();
getViewerJarEntryName(svattrib.getViewId()));
}
- List<String> pdbfilenames = new ArrayList<String>();
- List<SequenceI[]> seqmaps = new ArrayList<SequenceI[]>();
- List<String> pdbids = new ArrayList<String>();
+ List<String> pdbfilenames = new ArrayList<>();
+ List<SequenceI[]> seqmaps = new ArrayList<>();
+ List<String> pdbids = new ArrayList<>();
StringBuilder newFileLoc = new StringBuilder(64);
int cp = 0, ncp, ecp;
Map<File, StructureData> oldFiles = svattrib.getFileData();
af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
String[] renderOrder = new String[jms.getFeatureSettings()
.getSettingCount()];
- Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
- Map<String, Float> featureOrder = new Hashtable<String, Float>();
+ Map<String, FeatureColourI> featureColours = new Hashtable<>();
+ Map<String, Float> featureOrder = new Hashtable<>();
for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
{
fdi.setVisible(setting.getType());
}
}
- Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
+ Map<String, Boolean> fgtable = new Hashtable<>();
for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
{
Group grp = jms.getFeatureSettings().getGroup(gs);
String[] magicNames = new String[] { "Consensus", "Quality",
"Conservation" };
JvAnnotRow nullAnnot = new JvAnnotRow(-1, null);
- Hashtable<String, JvAnnotRow> visan = new Hashtable<String, JvAnnotRow>();
+ Hashtable<String, JvAnnotRow> visan = new Hashtable<>();
for (String nm : magicNames)
{
visan.put(nm, nullAnnot);
+ auan.template.getCalcId()), auan);
}
int hSize = al.getAlignmentAnnotation().length;
- List<JvAnnotRow> reorder = new ArrayList<JvAnnotRow>();
+ List<JvAnnotRow> reorder = new ArrayList<>();
// work through any autoCalculated annotation already on the view
// removing it if it should be placed in a different location on the
// annotation panel.
- List<String> remains = new ArrayList<String>(visan.keySet());
+ List<String> remains = new ArrayList<>(visan.keySet());
for (int h = 0; h < hSize; h++)
{
jalview.datamodel.AlignmentAnnotation jalan = al
{
if (datasetIds == null)
{
- datasetIds = new Hashtable<String, AlignmentI>();
+ datasetIds = new Hashtable<>();
return null;
}
if (datasetIds.containsKey(datasetId))
{
if (datasetIds == null)
{
- datasetIds = new Hashtable<String, AlignmentI>();
+ datasetIds = new Hashtable<>();
}
datasetIds.put(datasetId, dataset);
}
// make a new datasetId and record it
if (dataset2Ids == null)
{
- dataset2Ids = new IdentityHashMap<AlignmentI, String>();
+ dataset2Ids = new IdentityHashMap<>();
}
else
{
// register sequence object so the XML parser can recover it.
if (seqRefIds == null)
{
- seqRefIds = new HashMap<String, SequenceI>();
+ seqRefIds = new HashMap<>();
}
if (seqsToIds == null)
{
- seqsToIds = new IdentityHashMap<SequenceI, String>();
+ seqsToIds = new IdentityHashMap<>();
}
seqRefIds.put(jv2vobj.get(jvobj).toString(), (SequenceI) jvobj);
seqsToIds.put((SequenceI) jvobj, id);
private OverviewDimensions od;
+ private OverviewRenderer or = null;
+
private AlignViewportI av;
public OverviewCanvas(OverviewDimensions overviewDims,
if (updaterunning)
{
restart = true;
+ if (or != null)
+ {
+ or.setRedraw(true);
+ }
}
else
{
setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
- OverviewRenderer or = new OverviewRenderer(sr, fr, od);
+ or = new OverviewRenderer(sr, fr, od);
miniMe = or.draw(od.getRows(av.getAlignment()),
od.getColumns(av.getAlignment()));
@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;
+ }
+ }
}
}
}
- if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(seqs,
- features, true, ap))
+ /*
+ * an entirely gapped region will generate empty lists of sequence / features
+ */
+ if (!seqs.isEmpty())
{
- ap.alignFrame.setShowSeqFeatures(true);
- ap.highlightSearchResults(null);
+ if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(
+ seqs, features, true, ap))
+ {
+ ap.alignFrame.setShowSeqFeatures(true);
+ ap.av.setSearchResults(null); // clear highlighting
+ ap.repaint(); // draw new/amended features
+ }
}
}
import jalview.util.MessageManager;
import jalview.util.Platform;
import jalview.viewmodel.ViewportListenerI;
+import jalview.viewmodel.ViewportRanges;
import java.awt.Color;
import java.awt.FontMetrics;
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();
}
});
int res = (evt.getX() / av.getCharWidth())
+ av.getRanges().getStartRes();
+ reveal = av.getAlignment().getHiddenColumns()
+ .getRegionWithEdgeAtRes(res);
+
res = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(res);
- if (av.getAlignment().getHiddenColumns().getHiddenRegions() != null)
- {
- for (int[] region : av.getAlignment().getHiddenColumns()
- .getHiddenRegions())
- {
- if (res + 1 == region[0] || res - 1 == region[1])
- {
- reveal = region;
- ToolTipManager.sharedInstance().registerComponent(this);
- this.setToolTipText(MessageManager
- .getString("label.reveal_hidden_columns"));
- repaint();
- return;
- }
- }
- }
+ ToolTipManager.sharedInstance().registerComponent(this);
+ this.setToolTipText(
+ MessageManager.getString("label.reveal_hidden_columns"));
+ repaint();
}
/**
@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,
gg.setColor(Color.blue);
int res;
- if (av.getShowHiddenMarkers() && hidden.getHiddenRegions() != null)
+ if (av.getShowHiddenMarkers())
{
- for (int i = 0; i < hidden.getHiddenRegions()
- .size(); i++)
+ List<Integer> positions = hidden.findHiddenRegionPositions();
+ for (int pos : positions)
{
- res = hidden.findHiddenRegionPosition(i)
- - startx;
+ res = pos - startx;
if (res < 0 || res > widthx)
{
public void propertyChange(PropertyChangeEvent evt)
{
// Respond to viewport change events (e.g. alignment panel was scrolled)
- repaint();
+ // 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.STARTRES))
+ {
+ // scroll event, repaint panel
+ repaint();
+ }
}
}
*/
public class SeqCanvas extends JComponent implements ViewportListenerI
{
+ private static String ZEROS = "0000000000";
+
final FeatureRenderer fr;
final SequenceRenderer sr;
boolean fastPaint = false;
- int LABEL_WEST;
+ int labelWidthWest;
- int LABEL_EAST;
+ int labelWidthEast;
int cursorX = 0;
if (value != -1)
{
- int x = LABEL_WEST - fm.stringWidth(String.valueOf(value))
+ int x = labelWidthWest - fm.stringWidth(String.valueOf(value))
- charWidth / 2;
g.drawString(value + "", x, (ypos + (i * charHeight))
- (charHeight / 5));
fastpainting = true;
fastPaint = true;
updateViewport();
- gg.copyArea(horizontal * charWidth, vertical * charHeight, imgWidth,
- imgHeight, -horizontal * charWidth, -vertical * charHeight);
ViewportRanges ranges = av.getRanges();
int startRes = ranges.getStartRes();
int transX = 0;
int transY = 0;
+ gg.copyArea(horizontal * charWidth, vertical * charHeight, imgWidth,
+ imgHeight, -horizontal * charWidth, -vertical * charHeight);
+
if (horizontal > 0) // scrollbar pulled right, image to the left
{
transX = (endRes - startRes - horizontal) * charWidth;
}
/**
- * DOCUMENT ME!
+ * Returns the visible width of the canvas in residues, after allowing for
+ * East or West scales (if shown)
*
- * @param cwidth
- * DOCUMENT ME!
+ * @param canvasWidth
+ * the width in pixels (possibly including scales)
*
- * @return DOCUMENT ME!
+ * @return
*/
- public int getWrappedCanvasWidth(int cwidth)
+ public int getWrappedCanvasWidth(int canvasWidth)
{
FontMetrics fm = getFontMetrics(av.getFont());
- LABEL_EAST = 0;
- LABEL_WEST = 0;
+ labelWidthEast = 0;
+ labelWidthWest = 0;
if (av.getScaleRightWrapped())
{
- LABEL_EAST = fm.stringWidth(getMask());
+ labelWidthEast = getLabelWidth(fm);
}
if (av.getScaleLeftWrapped())
{
- LABEL_WEST = fm.stringWidth(getMask());
+ labelWidthWest = labelWidthEast > 0 ? labelWidthEast
+ : getLabelWidth(fm);
}
- return (cwidth - LABEL_EAST - LABEL_WEST) / charWidth;
+ return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
}
/**
- * Generates a string of zeroes.
+ * Returns a pixel width suitable for showing the largest sequence coordinate
+ * (end position) in the alignment. Returns 2 plus the number of decimal
+ * digits to be shown (3 for 1-10, 4 for 11-99 etc).
*
- * @return String
+ * @param fm
+ * @return
*/
- String getMask()
+ protected int getLabelWidth(FontMetrics fm)
{
- String mask = "00";
+ /*
+ * find the biggest sequence end position we need to show
+ * (note this is not necessarily the sequence length)
+ */
int maxWidth = 0;
- int tmp;
- for (int i = 0; i < av.getAlignment().getHeight(); i++)
+ AlignmentI alignment = av.getAlignment();
+ for (int i = 0; i < alignment.getHeight(); i++)
{
- tmp = av.getAlignment().getSequenceAt(i).getEnd();
- if (tmp > maxWidth)
- {
- maxWidth = tmp;
- }
+ maxWidth = Math.max(maxWidth, alignment.getSequenceAt(i).getEnd());
}
+ int length = 2;
for (int i = maxWidth; i > 0; i /= 10)
{
- mask += "0";
+ length++;
}
- return mask;
+
+ return fm.stringWidth(ZEROS.substring(0, length));
}
/**
updateViewport();
AlignmentI al = av.getAlignment();
- FontMetrics fm = getFontMetrics(av.getFont());
-
- if (av.getScaleRightWrapped())
+ int labelWidth = 0;
+ if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
{
- LABEL_EAST = fm.stringWidth(getMask());
+ FontMetrics fm = getFontMetrics(av.getFont());
+ labelWidth = getLabelWidth(fm);
}
- if (av.getScaleLeftWrapped())
- {
- LABEL_WEST = fm.stringWidth(getMask());
- }
+ labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0;
+ labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0;
int hgap = charHeight;
if (av.getScaleAboveWrapped())
hgap += charHeight;
}
- int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / charWidth;
+ int cWidth = (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
int cHeight = av.getAlignment().getHeight() * charHeight;
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();
+
while ((ypos <= canvasHeight) && (startRes < maxwidth))
{
endx = startRes + cWidth - 1;
if (av.getScaleRightWrapped())
{
- g.translate(canvasWidth - LABEL_EAST, 0);
+ g.translate(canvasWidth - labelWidthEast, 0);
drawEastScale(g, startRes, endx, ypos);
- g.translate(-(canvasWidth - LABEL_EAST), 0);
+ g.translate(-(canvasWidth - labelWidthEast), 0);
}
- g.translate(LABEL_WEST, 0);
+ g.translate(labelWidthWest, 0);
if (av.getScaleAboveWrapped())
{
g.setColor(Color.blue);
int res;
HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- for (int i = 0; i < hidden.getHiddenRegions().size(); i++)
+ List<Integer> positions = hidden.findHiddenRegionPositions();
+ for (int pos : positions)
{
- res = hidden.findHiddenRegionPosition(i) - startRes;
+ res = pos - startRes;
if (res < 0 || res > endx - startRes)
{
g.translate(0, -cHeight - ypos - 3);
}
g.setClip(clip);
- g.translate(-LABEL_WEST, 0);
+ g.translate(-labelWidthWest, 0);
- ypos += cHeight + getAnnotationHeight() + hgap;
+ ypos += cHeight + annotationHeight + hgap;
startRes += cWidth;
}
}
else
{
- List<int[]> regions = av.getAlignment().getHiddenColumns()
- .getHiddenRegions();
-
int screenY = 0;
final int screenYMax = endRes - startRes;
int blockStart = startRes;
int blockEnd = endRes;
- for (int[] region : regions)
+ for (int[] region : av.getAlignment().getHiddenColumns()
+ .getHiddenColumnsCopy())
{
int hideStart = region[0];
int hideEnd = region[1];
/**
* Highlights search results in the visible region by rendering as white text
- * on a black background. Any previous highlighting is removed.
+ * on a black background. Any previous highlighting is removed. Answers true
+ * if any highlight was left on the visible alignment (so status bar should be
+ * set to match), else false.
+ * <p>
+ * Currently fastPaint is not implemented for wrapped alignments. If a wrapped
+ * alignment had to be scrolled to show the highlighted region, then it should
+ * be fully redrawn, otherwise a fast paint can be performed. This argument
+ * could be removed if fast paint of scrolled wrapped alignment is coded in
+ * future (JAL-2609).
*
* @param results
+ * @param noFastPaint
+ * @return
*/
- public void highlightSearchResults(SearchResultsI results)
+ public boolean highlightSearchResults(SearchResultsI results,
+ boolean noFastPaint)
{
- updateViewport();
-
- /*
- * for now, don't attempt fastpaint if wrapped format
- */
- if (av.getWrapAlignment())
+ if (fastpainting)
{
- img = null;
- av.setSearchResults(results);
- repaint();
- return;
+ return false;
}
-
- fastpainting = true;
- fastPaint = true;
+ boolean wrapped = av.getWrapAlignment();
try
{
+ fastPaint = !noFastPaint;
+ fastpainting = fastPaint;
+
+ updateViewport();
+
/*
* to avoid redrawing the whole visible region, we instead
* redraw just the minimal regions to remove previous highlights
*/
SearchResultsI previous = av.getSearchResults();
av.setSearchResults(results);
- boolean redrawn = drawMappedPositions(previous);
- redrawn |= drawMappedPositions(results);
+ boolean redrawn = false;
+ boolean drawn = false;
+ if (wrapped)
+ {
+ redrawn = drawMappedPositionsWrapped(previous);
+ drawn = drawMappedPositionsWrapped(results);
+ redrawn |= drawn;
+ }
+ else
+ {
+ redrawn = drawMappedPositions(previous);
+ drawn = drawMappedPositions(results);
+ redrawn |= drawn;
+ }
+
+ /*
+ * if highlights were either removed or added, repaint
+ */
if (redrawn)
{
repaint();
}
+
+ /*
+ * return true only if highlights were added
+ */
+ return drawn;
+
} finally
{
fastpainting = false;
@Override
public void propertyChange(PropertyChangeEvent evt)
{
- if (!av.getWrapAlignment())
+ String eventName = evt.getPropertyName();
+
+ if (av.getWrapAlignment())
{
- if (evt.getPropertyName().equals("startres")
- || evt.getPropertyName().equals("endres"))
+ if (eventName.equals(ViewportRanges.STARTRES))
+ {
+ repaint();
+ }
+ }
+ else
+ {
+ int scrollX = 0;
+ if (eventName.equals(ViewportRanges.STARTRES))
{
// Make sure we're not trying to draw a panel
// larger than the visible window
ViewportRanges vpRanges = av.getRanges();
- int scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
- if (scrollX > vpRanges.getEndRes() - vpRanges.getStartRes())
+ scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+ int range = vpRanges.getEndRes() - vpRanges.getStartRes();
+ if (scrollX > range)
{
- scrollX = vpRanges.getEndRes() - vpRanges.getStartRes();
+ scrollX = range;
}
- else if (scrollX < vpRanges.getStartRes() - vpRanges.getEndRes())
+ else if (scrollX < -range)
{
- scrollX = vpRanges.getStartRes() - vpRanges.getEndRes();
+ scrollX = -range;
}
+ }
+
+ // 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 (eventName.equals(ViewportRanges.STARTRES))
+ {
+ // scroll - startres and endres both change
fastPaint(scrollX, 0);
}
- else if (evt.getPropertyName().equals("startseq")
- || evt.getPropertyName().equals("endseq"))
+ else if (eventName.equals(ViewportRanges.STARTSEQ))
{
+ // scroll
fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
}
}
}
+
+ /**
+ * Redraws any positions in the search results in the visible region of a
+ * wrapped alignment. Any highlights are drawn depending on the search results
+ * set on the Viewport, not the <code>results</code> argument. This allows
+ * this method to be called either to clear highlights (passing the previous
+ * search results), or to draw new highlights.
+ *
+ * @param results
+ * @return
+ */
+ protected boolean drawMappedPositionsWrapped(SearchResultsI results)
+ {
+ if (results == null)
+ {
+ return false;
+ }
+
+ boolean matchFound = false;
+
+ int wrappedWidth = av.getWrappedWidth();
+ int wrappedHeight = getRepeatHeightWrapped();
+
+ ViewportRanges ranges = av.getRanges();
+ int canvasHeight = getHeight();
+ int repeats = canvasHeight / wrappedHeight;
+ if (canvasHeight / wrappedHeight > 0)
+ {
+ repeats++;
+ }
+
+ int firstVisibleColumn = ranges.getStartRes();
+ int lastVisibleColumn = ranges.getStartRes() + repeats
+ * ranges.getViewportWidth() - 1;
+
+ AlignmentI alignment = av.getAlignment();
+ if (av.hasHiddenColumns())
+ {
+ firstVisibleColumn = alignment.getHiddenColumns()
+ .adjustForHiddenColumns(firstVisibleColumn);
+ lastVisibleColumn = alignment.getHiddenColumns()
+ .adjustForHiddenColumns(lastVisibleColumn);
+ }
+
+ int gapHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
+
+ for (int seqNo = ranges.getStartSeq(); seqNo <= ranges
+ .getEndSeq(); seqNo++)
+ {
+ SequenceI seq = alignment.getSequenceAt(seqNo);
+
+ int[] visibleResults = results.getResults(seq, firstVisibleColumn,
+ lastVisibleColumn);
+ if (visibleResults != null)
+ {
+ for (int i = 0; i < visibleResults.length - 1; i += 2)
+ {
+ int firstMatchedColumn = visibleResults[i];
+ int lastMatchedColumn = visibleResults[i + 1];
+ if (firstMatchedColumn <= lastVisibleColumn
+ && lastMatchedColumn >= firstVisibleColumn)
+ {
+ /*
+ * found a search results match in the visible region
+ */
+ firstMatchedColumn = Math.max(firstMatchedColumn,
+ firstVisibleColumn);
+ lastMatchedColumn = Math.min(lastMatchedColumn,
+ lastVisibleColumn);
+
+ /*
+ * draw each mapped position separately (as contiguous positions may
+ * wrap across lines)
+ */
+ for (int mappedPos = firstMatchedColumn; mappedPos <= lastMatchedColumn; mappedPos++)
+ {
+ int displayColumn = mappedPos;
+ if (av.hasHiddenColumns())
+ {
+ displayColumn = alignment.getHiddenColumns()
+ .findColumnPosition(displayColumn);
+ }
+
+ /*
+ * transX: offset from left edge of canvas to residue position
+ */
+ int transX = labelWidthWest
+ + ((displayColumn - ranges.getStartRes()) % wrappedWidth)
+ * av.getCharWidth();
+
+ /*
+ * transY: offset from top edge of canvas to residue position
+ */
+ int transY = gapHeight;
+ transY += (displayColumn - ranges.getStartRes())
+ / wrappedWidth * wrappedHeight;
+ transY += (seqNo - ranges.getStartSeq()) * av.getCharHeight();
+
+ /*
+ * yOffset is from graphics origin to start of visible region
+ */
+ int yOffset = 0;// (displayColumn / wrappedWidth) * wrappedHeight;
+ if (transY < getHeight())
+ {
+ matchFound = true;
+ gg.translate(transX, transY);
+ drawPanel(gg, displayColumn, displayColumn, seqNo, seqNo,
+ yOffset);
+ gg.translate(-transX, -transY);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return matchFound;
+ }
+
+ /**
+ * Answers the height in pixels of a repeating section of the wrapped
+ * alignment, including space above, scale above if shown, sequences, and
+ * annotation panel if shown
+ *
+ * @return
+ */
+ protected int getRepeatHeightWrapped()
+ {
+ // gap (and maybe scale) above
+ int repeatHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
+
+ // add sequences
+ repeatHeight += av.getRanges().getViewportHeight() * charHeight;
+
+ // add annotations panel height if shown
+ repeatHeight += getAnnotationHeight();
+
+ return repeatHeight;
+ }
}
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.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
}
lastSearchResults = results;
+ boolean wasScrolled = false;
+
if (av.isFollowHighlight())
{
// don't allow highlight of protein/cDNA to also scroll a complementary
// over residue to change abruptly, causing highlighted residue in panel 2
// to change, causing a scroll in panel 1 etc)
ap.setToScrollComplementPanel(false);
- if (ap.scrollToPosition(results, false))
+ wasScrolled = ap.scrollToPosition(results, false);
+ if (wasScrolled)
{
seqCanvas.revalidate();
}
ap.setToScrollComplementPanel(true);
}
- setStatusMessage(results);
- seqCanvas.highlightSearchResults(results);
+
+ boolean noFastPaint = wasScrolled && av.getWrapAlignment();
+ if (seqCanvas.highlightSearchResults(results, noFastPaint))
+ {
+ setStatusMessage(results);
+ }
}
@Override
SearchResultsI highlight = new SearchResults();
highlight.addResult(sequence, features.get(0).getBegin(), features
.get(0).getEnd());
- seqCanvas.highlightSearchResults(highlight);
+ seqCanvas.highlightSearchResults(highlight, false);
/*
* open the Amend Features dialog; clear highlighting afterwards,
List<SequenceI> seqs = Collections.singletonList(sequence);
seqCanvas.getFeatureRenderer().amendFeatures(seqs, features, false,
ap);
- seqCanvas.highlightSearchResults(null);
+ av.setSearchResults(null); // clear highlighting
+ seqCanvas.repaint(); // draw new/amended features
}
}
}
if (copycolsel
&& av.hasHiddenColumns()
- && (av.getAlignment().getHiddenColumns() == null || av
- .getAlignment().getHiddenColumns().getHiddenRegions() == null))
+ && (av.getAlignment().getHiddenColumns() == null))
{
System.err.println("Bad things");
}
*/
package jalview.gui;
+import jalview.analysis.Conservation;
import jalview.datamodel.SequenceGroup;
import jalview.jbgui.GSliderPanel;
import jalview.renderer.ResidueShaderI;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyVetoException;
+import java.util.List;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
"label.conservation_colour_increment",
new String[] { source == null ? BACKGROUND : source }));
- if (ap.av.getAlignment().getGroups() != null)
+ List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
+ if (groups != null && !groups.isEmpty())
{
sliderPanel.setAllGroupsCheckEnabled(true);
}
{
ap.av.setThreshold(percent);
}
- updateColourScheme(percent, cs);
+ updateColourScheme(percent, cs, null);
if (allGroupsCheck.isSelected())
{
- for (SequenceGroup sg : ap.av.getAlignment().getGroups())
+ List<SequenceGroup> groups = ap.av.getAlignment().getGroups();
+ for (SequenceGroup sg : groups)
{
- updateColourScheme(percent, sg.getGroupColourScheme());
+ updateColourScheme(percent, sg.getGroupColourScheme(), sg);
}
}
*
* @param percent
* @param scheme
+ * @param sg
*/
- protected void updateColourScheme(int percent, ResidueShaderI scheme)
+ protected void updateColourScheme(int percent, ResidueShaderI scheme,
+ SequenceGroup sg)
{
if (scheme == null)
{
}
if (forConservation)
{
+ if (!scheme.conservationApplied())
+ {
+ /*
+ * first time the colour scheme has had Conservation shading applied
+ * - compute conservation
+ */
+ Conservation c = new Conservation("Group", sg.getSequences(null),
+ sg.getStartRes(), sg.getEndRes());
+ c.calculate();
+ c.verdict(false, ap.av.getConsPercGaps());
+ sg.cs.setConservation(c);
+
+ }
+ scheme.setConservationApplied(true);
scheme.setConservationInc(percent);
}
else
public void setAllGroupsCheckEnabled(boolean b)
{
allGroupsCheck.setEnabled(b);
+ allGroupsCheck.setSelected(ap.av.getColourAppliesToAllGroups());
}
/**
if (cs != null && cs.hasHiddenColumns())
{
text.append("VIEW_HIDECOLS\t");
- List<int[]> hc = cs.getHiddenRegions();
- boolean comma = false;
- for (int[] r : hc)
- {
- if (!comma)
- {
- comma = true;
- }
- else
- {
- text.append(",");
- }
- text.append(r[0]);
- text.append("-");
- text.append(r[1]);
- }
+
+ String regions = cs.regionsToString(",", "-");
+ text.append(regions);
text.append("\n");
}
// TODO: allow efficient recovery of annotation data shown in several
StringBuffer colours = new StringBuffer();
StringBuffer graphLine = new StringBuffer();
StringBuffer rowprops = new StringBuffer();
- Hashtable<Integer, String> graphGroup = new Hashtable<Integer, String>();
- Hashtable<Integer, Object[]> graphGroup_refs = new Hashtable<Integer, Object[]>();
+ Hashtable<Integer, String> graphGroup = new Hashtable<>();
+ Hashtable<Integer, Object[]> graphGroup_refs = new Hashtable<>();
BitSet graphGroupSeen = new BitSet();
java.awt.Color color;
BufferedReader in) throws Exception
{
nlinesread = 0;
- ArrayList<Object[]> combineAnnotation_calls = new ArrayList<Object[]>();
- ArrayList<Object[]> deferredAnnotation_calls = new ArrayList<Object[]>();
+ ArrayList<Object[]> combineAnnotation_calls = new ArrayList<>();
+ ArrayList<Object[]> deferredAnnotation_calls = new ArrayList<>();
boolean modified = false;
String groupRef = null;
Hashtable groupRefRows = new Hashtable();
modified = true;
}
// Resolve the groupRefs
- Hashtable<String, SequenceGroup> groupRefLookup = new Hashtable<String, SequenceGroup>();
+ Hashtable<String, SequenceGroup> groupRefLookup = new Hashtable<>();
Enumeration en = groupRefRows.keys();
while (en.hasMoreElements())
// hidden column business
if (getViewport().hasHiddenColumns())
{
- List<int[]> hiddenCols = getViewport().getAlignment()
- .getHiddenColumns()
- .getHiddenRegions();
- StringBuilder hiddenColsBuilder = new StringBuilder();
- for (int[] range : hiddenCols)
- {
- hiddenColsBuilder.append(";").append(range[0]).append("-")
- .append(range[1]);
- }
-
- hiddenColsBuilder.deleteCharAt(0);
- hiddenSections[0] = hiddenColsBuilder.toString();
+ hiddenSections[0] = getViewport().getAlignment().getHiddenColumns()
+ .regionsToString(";", "-");
}
// hidden rows/seqs business
SequenceI[] sqs)
{
displayedFeatures = (fr == null) ? null : fr.getFeaturesDisplayed();
- List<SequenceFeaturesPojo> sequenceFeaturesPojo = new ArrayList<SequenceFeaturesPojo>();
+ List<SequenceFeaturesPojo> sequenceFeaturesPojo = new ArrayList<>();
if (sqs == null)
{
return sequenceFeaturesPojo;
public static List<AlignmentAnnotationPojo> annotationToJsonPojo(
Vector<AlignmentAnnotation> annotations)
{
- List<AlignmentAnnotationPojo> jsonAnnotations = new ArrayList<AlignmentAnnotationPojo>();
+ List<AlignmentAnnotationPojo> jsonAnnotations = new ArrayList<>();
if (annotations == null)
{
return jsonAnnotations;
parseHiddenCols(jvSettingsJsonObj);
}
- hiddenSequences = new ArrayList<SequenceI>();
- seqMap = new Hashtable<String, Sequence>();
+ hiddenSequences = new ArrayList<>();
+ seqMap = new Hashtable<>();
for (Iterator<JSONObject> sequenceIter = seqJsonArray.iterator(); sequenceIter
.hasNext();)
{
int endRes = Integer.valueOf(seqGrpObj.get("endRes").toString());
JSONArray sequenceRefs = (JSONArray) seqGrpObj.get("sequenceRefs");
- ArrayList<SequenceI> grpSeqs = new ArrayList<SequenceI>();
+ ArrayList<SequenceI> grpSeqs = new ArrayList<>();
if (sequenceRefs.size() > 0)
{
Iterator<String> seqHashIter = sequenceRefs.iterator();
public void parseHiddenSeqRefsAsList(JSONObject jvSettingsJson)
{
- hiddenSeqRefs = new ArrayList<String>();
+ hiddenSeqRefs = new ArrayList<>();
String hiddenSeqs = (String) jvSettingsJson.get("hiddenSeqs");
if (hiddenSeqs != null && !hiddenSeqs.isEmpty())
{
// raw number of pixels to allocate to each row
private float pixelsPerSeq;
+ // flag to indicate whether to halt drawing
+ private volatile boolean redraw = false;
+
public OverviewRenderer(jalview.api.SequenceRenderer seqRenderer,
FeatureRenderer fr, OverviewDimensions od)
- // FeatureColourFinder colfinder, OverviewDimensions od)
{
sr = seqRenderer;
- finder = new FeatureColourFinder(fr); // colfinder;
+ finder = new FeatureColourFinder(fr);
pixelsPerCol = od.getPixelsPerCol();
pixelsPerSeq = od.getPixelsPerSeq();
int rgbcolor = Color.white.getRGB();
int seqIndex = 0;
int pixelRow = 0;
+
for (int alignmentRow : rows)
{
+ if (redraw)
+ {
+ break;
+ }
+
// get details of this alignment row
boolean hidden = rows.isHidden(alignmentRow);
SequenceI seq = rows.getSequence(alignmentRow);
int pixelCol = 0;
for (int alignmentCol : cols)
{
+ if (redraw)
+ {
+ break;
+ }
+
// calculate where this column extends to in pixels
int endCol = Math.min(
Math.round((colIndex + 1) * pixelsPerCol) - 1,
int pixelCol = 0;
for (int alignmentCol : cols)
{
+ if (redraw)
+ {
+ break;
+ }
if (alignmentCol >= annotations.length)
{
break; // no more annotations to draw here
}
}
}
+
+ public void setRedraw(boolean b)
+ {
+ synchronized (this)
+ {
+ redraw = b;
+ }
+ }
}
}
/**
+ * Copy constructor
+ */
+ public ResidueShader(ResidueShader rs)
+ {
+ this.colourScheme = rs.colourScheme;
+ this.consensus = rs.consensus;
+ this.conservation = rs.conservation;
+ this.conservationColouring = rs.conservationColouring;
+ this.conservationIncrement = rs.conservationIncrement;
+ this.ignoreGaps = rs.ignoreGaps;
+ this.pidThreshold = rs.pidThreshold;
+ }
+
+ /**
* @see jalview.renderer.ResidueShaderI#setConsensus(jalview.datamodel.ProfilesI)
*/
@Override
for (SequenceFeature sf : overlaps)
{
Color featureColour = fc.getColor(sf);
- int visibleStart = Math.max(sf.getBegin(),
- visiblePositions.getBegin());
+ if (featureColour == null)
+ {
+ // score feature outwith threshold for colouring
+ continue;
+ }
+
+ /*
+ * if feature starts/ends outside the visible range,
+ * restrict to visible positions (or if a contact feature,
+ * to a single position)
+ */
+ int visibleStart = sf.getBegin();
+ if (visibleStart < visiblePositions.getBegin())
+ {
+ visibleStart = sf.isContactFeature() ? sf.getEnd()
+ : visiblePositions.getBegin();
+ }
+ int visibleEnd = sf.getEnd();
+ if (visibleEnd > visiblePositions.getEnd())
+ {
+ visibleEnd = sf.isContactFeature() ? sf.getBegin()
+ : visiblePositions.getEnd();
+ }
+
int featureStartCol = seq.findIndex(visibleStart);
- int visibleEnd = Math.min(sf.getEnd(), visiblePositions.getEnd());
int featureEndCol = sf.begin == sf.end ? featureStartCol : seq
.findIndex(visibleEnd);
- if (sf.isContactFeature())
+ // Color featureColour = getColour(sequenceFeature);
+
+ boolean isContactFeature = sf.isContactFeature();
+
+ if (isContactFeature)
{
boolean drawn = renderFeature(g, seq, featureStartCol - 1,
featureStartCol - 1, featureColour, start, end, y1,
drawnColour = featureColour;
}
}
- else if (showFeature(sf))
+ else
{
/*
* showing feature score by height of colour
* Returns the sequence feature colour rendered at the given column position,
* or null if none found. The feature of highest render order (i.e. on top) is
* found, subject to both feature type and feature group being visible, and
- * its colour returned.
+ * its colour returned. This method is suitable when no feature transparency
+ * applied (only the topmost visible feature colour is rendered).
* <p>
* Note this method does not check for a gap in the column so would return the
* colour for features enclosing a gapped column. Check for gap before calling
{
if (!featureGroupNotShown(sequenceFeature))
{
- return getColour(sequenceFeature);
+ Color col = getColour(sequenceFeature);
+ if (col != null)
+ {
+ return col;
+ }
}
}
}
return getColour();
}
- // todo should we check for above/below threshold here?
- if (range == 0.0)
- {
- return getMaxColour();
- }
+ /*
+ * graduated colour case, optionally with threshold
+ * Float.NaN is assigned minimum visible score colour
+ */
float scr = feature.getScore();
if (Float.isNaN(scr))
{
return getMinColour();
}
+ if (isAboveThreshold() && scr <= threshold)
+ {
+ return null;
+ }
+ if (isBelowThreshold() && scr >= threshold)
+ {
+ return null;
+ }
+ if (range == 0.0)
+ {
+ return getMaxColour();
+ }
float scl = (scr - base) / range;
if (isHighToLow)
{
return (isHighToLow) ? (base + range) : base;
}
- /**
- * Answers true if the feature has a simple colour, or is coloured by label,
- * or has a graduated colour and the score of this feature instance is within
- * the range to render (if any), i.e. does not lie below or above any
- * threshold set.
- *
- * @param feature
- * @return
- */
- @Override
- public boolean isColored(SequenceFeature feature)
- {
- if (isColourByLabel() || !isGraduatedColour())
- {
- return true;
- }
-
- float val = feature.getScore();
- if (Float.isNaN(val))
- {
- return true;
- }
- if (Float.isNaN(this.threshold))
- {
- return true;
- }
-
- if (isAboveThreshold() && val <= threshold)
- {
- return false;
- }
- if (isBelowThreshold() && val >= threshold)
- {
- return false;
- }
- return true;
- }
-
@Override
public boolean isSimpleColour()
{
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
-import jalview.util.Comparison;
import java.awt.Color;
import java.util.Map;
{
Color colour = Color.white;
- if (!Comparison.isGap(c) && colors != null && symbolIndex != null
+ if (colors != null && symbolIndex != null
&& c < symbolIndex.length
&& symbolIndex[c] < colors.length)
{
import jalview.datamodel.AnnotatedCollectionI;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
import java.awt.Color;
import java.util.Map;
*/
public class ScoreColourScheme extends ResidueColourScheme
{
- /** DOCUMENT ME!! */
public double min;
- /** DOCUMENT ME!! */
public double max;
- /** DOCUMENT ME!! */
public double[] scores;
/**
// Make colours in constructor
// Why wasn't this done earlier?
- int i, iSize = scores.length;
+ int iSize = scores.length;
colors = new Color[scores.length];
- for (i = 0; i < iSize; i++)
+ for (int i = 0; i < iSize; i++)
{
- float red = (float) (scores[i] - (float) min) / (float) (max - min);
+ /*
+ * scale score between min and max to the range 0.0 - 1.0
+ */
+ float score = (float) (scores[i] - (float) min) / (float) (max - min);
- if (red > 1.0f)
+ if (score > 1.0f)
{
- red = 1.0f;
+ score = 1.0f;
}
- if (red < 0.0f)
+ if (score < 0.0f)
{
- red = 0.0f;
+ score = 0.0f;
}
- colors[i] = makeColour(red);
+ colors[i] = makeColour(score);
}
}
+ @Override
+ public Color findColour(char c, int j, SequenceI seq)
+ {
+ if (Comparison.isGap(c))
+ {
+ return Color.white;
+ }
+ return super.findColour(c);
+ }
+
/**
* DOCUMENT ME!
*
* Cache a copy of the target sequences so we can mimic successive edits on
* them. This lets us compute mappings for all edits in the set.
*/
- Map<SequenceI, SequenceI> targetCopies = new HashMap<SequenceI, SequenceI>();
+ Map<SequenceI, SequenceI> targetCopies = new HashMap<>();
for (SequenceI seq : mapTo.getSequences())
{
SequenceI ds = seq.getDatasetSequence();
boolean undo, AlignmentI mapTo, List<AlignedCodonFrame> mappings)
{
SequenceI[] sortOrder = command.getSequenceOrder(undo);
- List<SequenceI> mappedOrder = new ArrayList<SequenceI>();
+ List<SequenceI> mappedOrder = new ArrayList<>();
int j = 0;
/*
AlignViewportI protein = targetIsNucleotide ? mapFrom : mapTo;
List<AlignedCodonFrame> codonFrames = protein.getAlignment()
.getCodonFrames();
- // ColumnSelection mappedColumns = new ColumnSelection();
if (colsel == null)
{
toSequences, fromGapChar);
}
- for (int[] hidden : hiddencols.getHiddenRegions())
+ for (int[] hidden : hiddencols.getHiddenColumnsCopy())
{
mapHiddenColumns(hidden, codonFrames, newHidden, fromSequences,
toSequences, fromGapChar);
public static List<char[]> findCodonsFor(SequenceI seq, int col,
List<AlignedCodonFrame> mappings)
{
- List<char[]> result = new ArrayList<char[]>();
+ List<char[]> result = new ArrayList<>();
int dsPos = seq.findPosition(col);
for (AlignedCodonFrame mapping : mappings)
{
SequenceI sequence, List<AlignedCodonFrame> mappings,
List<SequenceI> filterList)
{
- List<AlignedCodonFrame> result = new ArrayList<AlignedCodonFrame>();
+ List<AlignedCodonFrame> result = new ArrayList<>();
if (sequence == null || mappings == null)
{
return result;
public void setWrapAlignment(boolean state)
{
viewStyle.setWrapAlignment(state);
+ ranges.setWrappedMode(state);
}
/**
@Override
public boolean hasHiddenColumns()
{
- return colSel != null
+ return alignment.getHiddenColumns() != null
&& alignment.getHiddenColumns().hasHiddenColumns();
}
// 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());
}
}
{
return searchResults;
}
+
+ /**
+ * get the consensus sequence as displayed under the PID consensus annotation
+ * row.
+ *
+ * @return consensus sequence as a new sequence object
+ */
+ public SequenceI getConsensusSeq()
+ {
+ if (consensus == null)
+ {
+ updateConsensus(null);
+ }
+ if (consensus == null)
+ {
+ return null;
+ }
+ StringBuffer seqs = new StringBuffer();
+ for (int i = 0; i < consensus.annotations.length; i++)
+ {
+ Annotation annotation = consensus.annotations[i];
+ if (annotation != null)
+ {
+ String description = annotation.description;
+ if (description != null && description.startsWith("["))
+ {
+ // consensus is a tie - just pick the first one
+ seqs.append(description.charAt(1));
+ }
+ else
+ {
+ seqs.append(annotation.displayCharacter);
+ }
+ }
+ }
+
+ SequenceI sq = new Sequence("Consensus", seqs.toString());
+ sq.setDescription("Percentage Identity Consensus "
+ + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
+ return sq;
+ }
}
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 class ViewportRanges extends ViewportProperties
{
+ public static final String STARTRES = "startres";
+
+ public static final String ENDRES = "endres";
+
+ public static final String STARTSEQ = "startseq";
+
+ 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
{
endRes = end;
}
- changeSupport.firePropertyChange("startres", oldstartres, startRes);
+ changeSupport.firePropertyChange(STARTRES, oldstartres, startRes);
if (oldstartres == startRes)
{
// event won't be fired if start positions are same
// fire an event for the end positions in case they changed
- changeSupport.firePropertyChange("endres", oldendres, endRes);
- }
- }
-
- /**
- * 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;
+ changeSupport.firePropertyChange(ENDRES, oldendres, endRes);
}
- setStartEndRes(startres - width + 1, startres);
}
/**
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)
{
endSeq = end;
}
- changeSupport.firePropertyChange("startseq", oldstartseq, startSeq);
+ changeSupport.firePropertyChange(STARTSEQ, oldstartseq, startSeq);
if (oldstartseq == startSeq)
{
// event won't be fired if start positions are the same
// fire in case the end positions changed
- changeSupport.firePropertyChange("endseq", oldendseq, endSeq);
+ changeSupport.firePropertyChange(ENDSEQ, oldendseq, endSeq);
}
}
{
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);
}
}
/**
- * Scroll a wrapped alignment so that the specified residue is visible. Fires
- * a property change event.
+ * Scroll a wrapped alignment so that the specified residue is in the first
+ * repeat of the wrapped view. Fires a property change event. Answers true if
+ * the startRes changed, else false.
*
* @param res
* residue position to scroll to
+ * @return
*/
- public void scrollToWrappedVisible(int res)
+ public boolean scrollToWrappedVisible(int res)
{
- // get the start residue of the wrapped row which res is in
- // and set that as our start residue
+ int oldStartRes = startRes;
int width = getViewportWidth();
- setStartRes((res / width) * width);
+
+ if (res >= oldStartRes && res < oldStartRes + width)
+ {
+ return false;
+ }
+
+ boolean up = res < oldStartRes;
+ int widthsToScroll = Math.abs((res - oldStartRes) / width);
+ if (up)
+ {
+ widthsToScroll++;
+ }
+
+ int residuesToScroll = width * widthsToScroll;
+ int newStartRes = up ? oldStartRes - residuesToScroll : oldStartRes
+ + residuesToScroll;
+ if (newStartRes < 0)
+ {
+ newStartRes = 0;
+ }
+
+ setStartRes(newStartRes);
+
+ return true;
}
/**
*/
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;
}
}
* Returns the configured colour for a particular feature instance. This
* includes calculation of 'colour by label', or of a graduated score colour,
* if applicable. It does not take into account feature visibility or colour
- * transparency.
+ * transparency. Returns null for a score feature whose score value lies
+ * outside any colour threshold.
*
* @param feature
* @return
}
/**
- * Answers true unless the feature has a graduated colour scheme and the
- * feature value lies outside the current threshold for display
- *
- * @param sequenceFeature
- * @return
- */
- protected boolean showFeature(SequenceFeature sequenceFeature)
- {
- FeatureColourI fc = getFeatureStyle(sequenceFeature.type);
- return fc.isColored(sequenceFeature);
- }
-
- /**
* Answers true if the feature type is currently selected to be displayed,
* else false
*
import jalview.util.MapList;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
"addSequence broke dataset reference integrity");
}
- @Test(groups = "Functional")
- public void getVisibleStartAndEndIndexTest()
- {
- Sequence seq = new Sequence("testSeq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- AlignmentI align = new Alignment(new SequenceI[] { seq });
- ArrayList<int[]> hiddenCols = new ArrayList<int[]>();
-
- int[] startEnd = align.getVisibleStartAndEndIndex(hiddenCols);
- assertEquals(0, startEnd[0]);
- assertEquals(25, startEnd[1]);
-
- hiddenCols.add(new int[] { 0, 0 });
- startEnd = align.getVisibleStartAndEndIndex(hiddenCols);
- assertEquals(1, startEnd[0]);
- assertEquals(25, startEnd[1]);
-
- hiddenCols.add(new int[] { 6, 9 });
- hiddenCols.add(new int[] { 11, 12 });
- startEnd = align.getVisibleStartAndEndIndex(hiddenCols);
- assertEquals(1, startEnd[0]);
- assertEquals(25, startEnd[1]);
-
- hiddenCols.add(new int[] { 24, 25 });
- startEnd = align.getVisibleStartAndEndIndex(hiddenCols);
- System.out.println(startEnd[0] + " : " + startEnd[1]);
- assertEquals(1, startEnd[0]);
- assertEquals(23, startEnd[1]);
- }
-
/**
* Tests that dbrefs with mappings to sequence get updated if the sequence
* acquires a dataset sequence
// hide column 5 (and adjacent):
cs.hideSelectedColumns(5, al.getHiddenColumns());
// 4,5,6 now hidden:
- List<int[]> hidden = al.getHiddenColumns().getHiddenRegions();
+ List<int[]> hidden = al.getHiddenColumns().getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
// none now selected:
cs.addElement(5);
cs.addElement(6);
cs.hideSelectedColumns(4, al.getHiddenColumns());
- hidden = al.getHiddenColumns().getHiddenRegions();
+ hidden = al.getHiddenColumns().getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
cs.addElement(5);
cs.addElement(6);
cs.hideSelectedColumns(6, al.getHiddenColumns());
- hidden = al.getHiddenColumns().getHiddenRegions();
+ hidden = al.getHiddenColumns().getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
cs.addElement(4);
cs.addElement(6);
cs.hideSelectedColumns(5, al.getHiddenColumns());
- hidden = al.getHiddenColumns().getHiddenRegions();
+ hidden = al.getHiddenColumns().getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
cs.hideSelectedColumns(al);
assertTrue(cs.getSelected().isEmpty());
- List<int[]> hidden = cols.getHiddenRegions();
+ List<int[]> hidden = cols.getHiddenColumnsCopy();
assertEquals(4, hidden.size());
assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
assertEquals("[7, 9]", Arrays.toString(hidden.get(1)));
*/
package jalview.datamodel;
+import static org.testng.Assert.assertNull;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
import jalview.analysis.AlignmentGenerator;
HiddenColumns cs = new HiddenColumns();
cs.hideColumns(10, 11);
cs.hideColumns(5, 7);
- assertEquals("[5, 7]", Arrays.toString(cs.getHiddenRegions().get(0)));
+ assertEquals("[5, 7]",
+ Arrays.toString(cs.getHiddenColumnsCopy().get(0)));
HiddenColumns cs2 = new HiddenColumns(cs);
assertTrue(cs2.hasHiddenColumns());
- assertEquals(2, cs2.getHiddenRegions().size());
+ assertEquals(2, cs2.getHiddenColumnsCopy().size());
// hidden columns are held in column order
- assertEquals("[5, 7]", Arrays.toString(cs2.getHiddenRegions().get(0)));
- assertEquals("[10, 11]", Arrays.toString(cs2.getHiddenRegions().get(1)));
+ assertEquals("[5, 7]",
+ Arrays.toString(cs2.getHiddenColumnsCopy().get(0)));
+ assertEquals("[10, 11]",
+ Arrays.toString(cs2.getHiddenColumnsCopy().get(1)));
}
/**
ColumnSelection colsel = new ColumnSelection();
HiddenColumns cs = al.getHiddenColumns();
colsel.hideSelectedColumns(5, al.getHiddenColumns());
- List<int[]> hidden = cs.getHiddenRegions();
+ List<int[]> hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[5, 5]", Arrays.toString(hidden.get(0)));
colsel.hideSelectedColumns(3, al.getHiddenColumns());
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(2, hidden.size());
// two hidden ranges, in order:
- assertSame(hidden, cs.getHiddenRegions());
+ assertEquals(hidden.size(), cs.getHiddenColumnsCopy().size());
assertEquals("[3, 3]", Arrays.toString(hidden.get(0)));
assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
// hiding column 4 expands [3, 3] to [3, 4]
// and merges to [5, 5] to make [3, 5]
colsel.hideSelectedColumns(4, al.getHiddenColumns());
- hidden = cs.getHiddenRegions();
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[3, 5]", Arrays.toString(hidden.get(0)));
// clear hidden columns (note they are added to selected)
cs.revealAllHiddenColumns(colsel);
// it is now actually null but getter returns an empty list
- assertTrue(cs.getHiddenRegions().isEmpty());
+ assertTrue(cs.getHiddenColumnsCopy().isEmpty());
cs.hideColumns(3, 6);
- hidden = cs.getHiddenRegions();
+ hidden = cs.getHiddenColumnsCopy();
int[] firstHiddenRange = hidden.get(0);
assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
// adding a subrange of already hidden should do nothing
cs.hideColumns(4, 5);
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
- assertSame(firstHiddenRange, cs.getHiddenRegions().get(0));
+ assertEquals("[3, 6]",
+ Arrays.toString(cs.getHiddenColumnsCopy().get(0)));
cs.hideColumns(3, 5);
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
- assertSame(firstHiddenRange, cs.getHiddenRegions().get(0));
+ assertEquals("[3, 6]",
+ Arrays.toString(cs.getHiddenColumnsCopy().get(0)));
cs.hideColumns(4, 6);
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
- assertSame(firstHiddenRange, cs.getHiddenRegions().get(0));
+ assertEquals("[3, 6]",
+ Arrays.toString(cs.getHiddenColumnsCopy().get(0)));
cs.hideColumns(3, 6);
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
- assertSame(firstHiddenRange, cs.getHiddenRegions().get(0));
+ assertEquals("[3, 6]",
+ Arrays.toString(cs.getHiddenColumnsCopy().get(0)));
cs.revealAllHiddenColumns(colsel);
cs.hideColumns(2, 4);
- hidden = cs.getHiddenRegions();
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
// extend contiguous with 2 positions overlap
cs.hideColumns(3, 5);
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[2, 5]", Arrays.toString(hidden.get(0)));
// extend contiguous with 1 position overlap
cs.hideColumns(5, 6);
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[2, 6]", Arrays.toString(hidden.get(0)));
// extend contiguous with overlap both ends:
cs.hideColumns(1, 7);
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[1, 7]", Arrays.toString(hidden.get(0)));
}
colsel.addElement(10);
cs.revealHiddenColumns(5, colsel);
// hidden columns list now null but getter returns empty list:
- assertTrue(cs.getHiddenRegions().isEmpty());
+ assertTrue(cs.getHiddenColumnsCopy().isEmpty());
// revealed columns are marked as selected (added to selection):
assertEquals("[10, 5, 6, 7, 8]", colsel.getSelected().toString());
colsel = new ColumnSelection();
cs = new HiddenColumns();
cs.hideColumns(5, 8);
- List<int[]> hidden = cs.getHiddenRegions();
+ List<int[]> hidden = cs.getHiddenColumnsCopy();
cs.revealHiddenColumns(6, colsel);
- assertSame(hidden, cs.getHiddenRegions());
+ assertEquals(hidden.size(), cs.getHiddenColumnsCopy().size());
assertTrue(colsel.getSelected().isEmpty());
}
* revealing hidden columns adds them (in order) to the (unordered)
* selection list
*/
- assertTrue(cs.getHiddenRegions().isEmpty());
+ assertTrue(cs.getHiddenColumnsCopy().isEmpty());
assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]", colsel.getSelected()
.toString());
}
HiddenColumns cs = new HiddenColumns();
cs.hideColumns(49, 59);
cs.hideColumns(69, 79);
- List<int[]> hidden = cs.getHiddenRegions();
+ List<int[]> hidden = cs.getHiddenColumnsCopy();
assertEquals(2, hidden.size());
assertEquals("[49, 59]", Arrays.toString(hidden.get(0)));
assertEquals("[69, 79]", Arrays.toString(hidden.get(1)));
cs.hideColumns(48, 80);
- hidden = cs.getHiddenRegions();
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[48, 80]", Arrays.toString(hidden.get(0)));
cs.hideColumns(50, 60);
// hiding 21-49 should merge to one range
cs.hideColumns(21, 49);
- hidden = cs.getHiddenRegions();
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[10, 60]", Arrays.toString(hidden.get(0)));
cs.hideColumns(60, 70);
cs.hideColumns(15, 45);
- hidden = cs.getHiddenRegions();
+ hidden = cs.getHiddenColumnsCopy();
assertEquals(2, hidden.size());
assertEquals("[10, 50]", Arrays.toString(hidden.get(0)));
assertEquals("[60, 70]", Arrays.toString(hidden.get(1)));
one.set(1);
cs = new HiddenColumns();
cs.hideMarkedBits(one);
- assertEquals(1, cs.getHiddenRegions().size());
+ assertEquals(1, cs.getHiddenColumnsCopy().size());
one.set(2);
cs = new HiddenColumns();
cs.hideMarkedBits(one);
- assertEquals(1, cs.getHiddenRegions().size());
+ assertEquals(1, cs.getHiddenColumnsCopy().size());
one.set(3);
cs = new HiddenColumns();
cs.hideMarkedBits(one);
- assertEquals(1, cs.getHiddenRegions().size());
+ assertEquals(1, cs.getHiddenColumnsCopy().size());
// split
one.clear(2);
cs = new HiddenColumns();
cs.hideMarkedBits(one);
- assertEquals(2, cs.getHiddenRegions().size());
+ assertEquals(2, cs.getHiddenColumnsCopy().size());
assertEquals(0, cs.adjustForHiddenColumns(0));
assertEquals(2, cs.adjustForHiddenColumns(1));
cs = new HiddenColumns();
cs.hideMarkedBits(one);
- assertEquals(1, cs.getHiddenRegions().size());
+ assertEquals(1, cs.getHiddenColumnsCopy().size());
assertEquals(0, cs.adjustForHiddenColumns(0));
assertEquals(1, cs.adjustForHiddenColumns(1));
assertEquals(toMark, fromMark);
}
}
+
+ @Test(groups = { "Functional" })
+ public void testFindHiddenRegionPositions()
+ {
+ HiddenColumns hc = new HiddenColumns();
+
+ List<Integer> positions = hc.findHiddenRegionPositions();
+ assertTrue(positions.isEmpty());
+
+ hc.hideColumns(3, 7);
+ hc.hideColumns(10, 10);
+ hc.hideColumns(14, 15);
+
+ positions = hc.findHiddenRegionPositions();
+ assertEquals(3, positions.size());
+ assertEquals(3, positions.get(0).intValue());
+ assertEquals(5, positions.get(1).intValue());
+ assertEquals(8, positions.get(2).intValue());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testRegionsToString()
+ {
+ HiddenColumns hc = new HiddenColumns();
+
+ String result = hc.regionsToString(",", "--");
+ assertEquals("", result);
+
+ hc.hideColumns(3, 7);
+ hc.hideColumns(10, 10);
+ hc.hideColumns(14, 15);
+
+ result = hc.regionsToString(",", "--");
+ assertEquals("3--7,10--10,14--15", result);
+ }
+
+ @Test(groups = "Functional")
+ public void getVisibleStartAndEndIndexTest()
+ {
+ Sequence seq = new Sequence("testSeq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ AlignmentI align = new Alignment(new SequenceI[] { seq });
+ HiddenColumns hc = new HiddenColumns();
+
+ int[] startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
+ assertEquals(0, startEnd[0]);
+ assertEquals(25, startEnd[1]);
+
+ hc.hideColumns(0, 0);
+ startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
+ assertEquals(1, startEnd[0]);
+ assertEquals(25, startEnd[1]);
+
+ hc.hideColumns(6, 9);
+ hc.hideColumns(11, 12);
+ startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
+ assertEquals(1, startEnd[0]);
+ assertEquals(25, startEnd[1]);
+
+ hc.hideColumns(24, 25);
+ startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
+ System.out.println(startEnd[0] + " : " + startEnd[1]);
+ assertEquals(1, startEnd[0]);
+ assertEquals(23, startEnd[1]);
+ }
+
+ @Test(groups = "Functional")
+ public void testGetRegionWithEdgeAtRes()
+ {
+ HiddenColumns hc = new HiddenColumns();
+
+ int[] result = hc.getRegionWithEdgeAtRes(5);
+ assertNull(result);
+
+ hc.hideColumns(3, 7);
+ hc.hideColumns(10, 10);
+ hc.hideColumns(14, 15);
+
+ result = hc.getRegionWithEdgeAtRes(3);
+ assertEquals(3, result[0]);
+ assertEquals(7, result[1]);
+
+ result = hc.getRegionWithEdgeAtRes(5);
+ assertEquals(10, result[0]);
+ assertEquals(10, result[1]);
+
+ result = hc.getRegionWithEdgeAtRes(6);
+ assertNull(result);
+ }
+
+ @Test(groups = "Functional")
+ public void testPropagateInsertions()
+ {
+ // create an alignment with no gaps - this will be the profile seq and other
+ // JPRED seqs
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI al = gen.generate(20, 10, 1234, 0, 0);
+
+ // get the profileseq
+ SequenceI profileseq = al.getSequenceAt(0);
+ SequenceI gappedseq = new Sequence(profileseq);
+ gappedseq.insertCharAt(5, al.getGapCharacter());
+ gappedseq.insertCharAt(6, al.getGapCharacter());
+ gappedseq.insertCharAt(7, al.getGapCharacter());
+ gappedseq.insertCharAt(8, al.getGapCharacter());
+
+ // create an alignment view with the gapped sequence
+ SequenceI[] seqs = new SequenceI[1];
+ seqs[0] = gappedseq;
+ AlignmentI newal = new Alignment(seqs);
+ HiddenColumns hidden = new HiddenColumns();
+ hidden.hideColumns(15, 17);
+
+ AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
+ false);
+
+ // confirm that original contigs are as expected
+ int[] oldcontigs = hidden.getVisibleContigs(0, 20);
+ int[] testcontigs = { 0, 14, 18, 19 };
+ assertTrue(Arrays.equals(oldcontigs, testcontigs));
+
+ // propagate insertions
+ HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
+ view);
+
+ // confirm that the contigs have changed to account for the gaps
+ int[] newcontigs = result.getVisibleContigs(0, 20);
+ testcontigs[1] = 10;
+ testcontigs[2] = 14;
+ assertTrue(Arrays.equals(newcontigs, testcontigs));
+
+ }
}
{
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));
+ }
}
/**
}
@Test(groups = { "Functional" })
- public void testCopyConstructor()
+ public void testCopyConstructors()
{
SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33,
12.5f, "group");
assertEquals("desc", sf2.getDescription());
assertEquals(22, sf2.getBegin());
assertEquals(33, sf2.getEnd());
+ assertEquals(12.5f, sf2.getScore());
assertEquals("+", sf2.getValue("STRAND"));
assertEquals("Testing", sf2.getValue("Note"));
// shallow clone of otherDetails map - contains the same object values!
assertSame(count, sf2.getValue("Count"));
+
+ /*
+ * copy constructor modifying begin/end/group/score
+ */
+ SequenceFeature sf3 = new SequenceFeature(sf1, 11, 14, "group2", 17.4f);
+ assertEquals("type", sf3.getType());
+ assertEquals("desc", sf3.getDescription());
+ assertEquals(11, sf3.getBegin());
+ assertEquals(14, sf3.getEnd());
+ assertEquals(17.4f, sf3.getScore());
+ assertEquals("+", sf3.getValue("STRAND"));
+ assertEquals("Testing", sf3.getValue("Note"));
+ // shallow clone of otherDetails map - contains the same object values!
+ assertSame(count, sf3.getValue("Count"));
+
+ /*
+ * copy constructor modifying type/begin/end/group/score
+ */
+ SequenceFeature sf4 = new SequenceFeature(sf1, "Disulfide bond", 12,
+ 15, "group3", -9.1f);
+ assertEquals("Disulfide bond", sf4.getType());
+ assertTrue(sf4.isContactFeature());
+ assertEquals("desc", sf4.getDescription());
+ assertEquals(12, sf4.getBegin());
+ assertEquals(15, sf4.getEnd());
+ assertEquals(-9.1f, sf4.getScore());
+ assertEquals("+", sf4.getValue("STRAND"));
+ assertEquals("Testing", sf4.getValue("Note"));
+ // shallow clone of otherDetails map - contains the same object values!
+ assertSame(count, sf4.getValue("Count"));
}
/**
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
+import jalview.analysis.Conservation;
import jalview.schemes.NucleotideColourScheme;
import jalview.schemes.PIDColourScheme;
import java.awt.Color;
+import java.util.Collections;
import junit.extensions.PA;
sg.setName("g1");
sg.setDescription("desc");
sg.setColourScheme(new PIDColourScheme());
+ Conservation cons = new Conservation("Cons", 2,
+ Collections.<SequenceI> emptyList(), 3, 12);
+ PA.setValue(cons, "consSequence", new Sequence("s", "abc"));
+ sg.getGroupColourScheme().setConservation(cons);
+ sg.getGroupColourScheme().setConsensus(new Profiles(null));
sg.setDisplayBoxes(false);
sg.setDisplayText(false);
sg.setColourText(true);
assertEquals(sg2.getDescription(), sg.getDescription());
assertNotSame(sg2.getGroupColourScheme(), sg.getGroupColourScheme());
assertSame(sg2.getColourScheme(), sg.getColourScheme());
+ assertSame(PA.getValue(sg2.getGroupColourScheme(), "consensus"),
+ PA.getValue(sg.getGroupColourScheme(), "consensus"));
+ assertSame(PA.getValue(sg2.getGroupColourScheme(), "conservation"),
+ PA.getValue(sg.getGroupColourScheme(), "conservation"));
assertEquals(sg2.getDisplayBoxes(), sg.getDisplayBoxes());
assertEquals(sg2.getDisplayText(), sg.getDisplayText());
assertEquals(sg2.getColourText(), sg.getColourText());
assertFalse(alignFrame.hideFeatureColumns("exon", true));
assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
assertTrue(alignFrame.getViewport().getAlignment().getHiddenColumns()
- .getHiddenRegions()
+ .getHiddenColumnsCopy()
.isEmpty());
assertFalse(alignFrame.hideFeatureColumns("exon", false));
assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
assertTrue(alignFrame.getViewport().getAlignment().getHiddenColumns()
- .getHiddenRegions()
+ .getHiddenColumnsCopy()
.isEmpty());
/*
assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
List<int[]> hidden = alignFrame.getViewport().getAlignment()
.getHiddenColumns()
- .getHiddenRegions();
+ .getHiddenColumnsCopy();
assertTrue(hidden.isEmpty());
/*
*/
assertTrue(alignFrame.hideFeatureColumns("Turn", true));
hidden = alignFrame.getViewport().getAlignment().getHiddenColumns()
- .getHiddenRegions();
+ .getHiddenColumnsCopy();
assertEquals(hidden.size(), 2);
assertEquals(hidden.get(0)[0], 1);
assertEquals(hidden.get(0)[1], 3);
import jalview.schemes.PIDColourScheme;
import jalview.structure.StructureSelectionManager;
import jalview.util.MapList;
+import jalview.viewmodel.ViewportRanges;
import java.util.ArrayList;
import java.util.List;
}
;
Assert.assertEquals(c, 1, "Expected to find one occupancy row.");
+ }
+ @Test(groups = { "Functional" })
+ public void testGetConsensusSeq()
+ {
+ /*
+ * A-C
+ * A-C
+ * A-D
+ * --D
+ * consensus expected to be A-C
+ */
+ String fasta = ">s1\nA-C\n>s2\nA-C\n>s3\nA-D\n>s4\n--D\n";
+ AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(fasta,
+ DataSourceType.PASTE);
+ AlignViewport testme = af.getViewport();
+ 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());
}
}
private Alignment alignment;
- private HashMap<String, SequenceI> expectedSeqs = new HashMap<String, SequenceI>();
+ private HashMap<String, SequenceI> expectedSeqs = new HashMap<>();
- private HashMap<String, AlignmentAnnotation> expectedAnnots = new HashMap<String, AlignmentAnnotation>();
+ private HashMap<String, AlignmentAnnotation> expectedAnnots = new HashMap<>();
- private HashMap<String, SequenceGroup> expectedGrps = new HashMap<String, SequenceGroup>();
+ private HashMap<String, SequenceGroup> expectedGrps = new HashMap<>();
private HiddenColumns expectedColSel = new HiddenColumns();
}
// create and add a sequence group
- List<SequenceI> grpSeqs = new ArrayList<SequenceI>();
+ List<SequenceI> grpSeqs = new ArrayList<>();
grpSeqs.add(seqs[1]);
grpSeqs.add(seqs[2]);
grpSeqs.add(seqs[3]);
TEST_SEQ_HEIGHT = expectedSeqs.size();
TEST_GRP_HEIGHT = expectedGrps.size();
TEST_ANOT_HEIGHT = expectedAnnots.size();
- TEST_CS_HEIGHT = expectedColSel.getHiddenRegions().size();
+ TEST_CS_HEIGHT = expectedColSel.getHiddenColumnsCopy().size();
exportSettings = new AlignExportSettingI()
{
{
HiddenColumns cs = testJsonFile.getHiddenColumns();
Assert.assertNotNull(cs);
- Assert.assertNotNull(cs.getHiddenRegions());
- List<int[]> hiddenCols = cs.getHiddenRegions();
+ Assert.assertNotNull(cs.getHiddenColumnsCopy());
+ List<int[]> hiddenCols = cs.getHiddenColumnsCopy();
Assert.assertEquals(hiddenCols.size(), TEST_CS_HEIGHT);
Assert.assertEquals(hiddenCols.get(0), expectedColSel
- .getHiddenRegions().get(0),
+ .getHiddenColumnsCopy().get(0),
"Mismatched hidden columns!");
}
FeatureColourFinder finder2 = new FeatureColourFinder(null);
assertTrue(finder2.noFeaturesDisplayed());
}
+
+ @Test(groups = "Functional")
+ public void testFindFeatureColour_graduatedWithThreshold()
+ {
+ String kdFeature = "kd";
+ String metalFeature = "Metal";
+ seq.addSequenceFeature(new SequenceFeature(kdFeature, "hydrophobicity", 2,
+ 2, 0f, "KdGroup"));
+ seq.addSequenceFeature(new SequenceFeature(kdFeature, "hydrophobicity", 4,
+ 4, 5f, "KdGroup"));
+ seq.addSequenceFeature(new SequenceFeature(metalFeature, "Fe", 4, 4,
+ 5f, "MetalGroup"));
+ seq.addSequenceFeature(new SequenceFeature(kdFeature, "hydrophobicity", 7,
+ 7, 10f, "KdGroup"));
+
+ /*
+ * kd feature has 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(kdFeature, fc);
+ FeatureColour green = new FeatureColour(Color.green);
+ fr.setColour(metalFeature, green);
+ fr.featuresAdded();
+
+ /*
+ * render order is kd above Metal
+ */
+ Object[][] data = new Object[2][];
+ data[0] = new Object[] { kdFeature, fc, true };
+ data[1] = new Object[] { metalFeature, green, true };
+ fr.setFeaturePriority(data);
+
+ 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
+ * should return Green (colour of Metal feature)
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 3);
+ assertEquals(c, Color.green);
+
+ /*
+ * 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
+ * should return Green (colour of Metal feature)
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 3);
+ assertEquals(c, Color.green);
+
+ /*
+ * position 7, column 9, score 10 - above threshold - default colour
+ */
+ c = finder.findFeatureColour(Color.blue, seq, 9);
+ assertEquals(c, Color.blue);
+ }
}
fr.filterFeaturesForDisplay(features, null); // empty list, does nothing
SequenceI seq = av.getAlignment().getSequenceAt(0);
- SequenceFeature sf1 = new SequenceFeature("Cath", "", 6, 8, "group1");
+ SequenceFeature sf1 = new SequenceFeature("Cath", "", 6, 8, Float.NaN,
+ "group1");
seq.addSequenceFeature(sf1);
- SequenceFeature sf2 = new SequenceFeature("Cath", "", 5, 11, "group2");
+ SequenceFeature sf2 = new SequenceFeature("Cath", "", 5, 11, 2f,
+ "group2");
seq.addSequenceFeature(sf2);
- SequenceFeature sf3 = new SequenceFeature("Cath", "", 5, 11, "group3");
+ SequenceFeature sf3 = new SequenceFeature("Cath", "", 5, 11, 3f,
+ "group3");
seq.addSequenceFeature(sf3);
- SequenceFeature sf4 = new SequenceFeature("Cath", "", 6, 8, "group4");
+ SequenceFeature sf4 = new SequenceFeature("Cath", "", 6, 8, 4f,
+ "group4");
seq.addSequenceFeature(sf4);
- SequenceFeature sf5 = new SequenceFeature("Cath", "", 6, 9, "group4");
+ SequenceFeature sf5 = new SequenceFeature("Cath", "", 6, 9, 5f,
+ "group4");
seq.addSequenceFeature(sf5);
fr.findAllFeatures(true);
/*
* no filtering of co-located features with graduated colour scheme
+ * filterFeaturesForDisplay does _not_ check colour threshold
* sf2 is removed as its group is hidden
*/
features = seq.getSequenceFeatures();
--- /dev/null
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class BuriedColourSchemeTest
+{
+ /**
+ * Turn colours are based on the scores in ResidueProperties.buried A = 1.7, R
+ * = 0.1, N = 0.4, D = 0.4... min = 0.05 max = 4.6
+ * <p>
+ * scores are scaled to c 0-1 between min and max and colour is (0, 1-c, c)
+ */
+ @Test(groups = "Functional")
+ public void testFindColour()
+ {
+ ScoreColourScheme scheme = new BuriedColourScheme();
+
+ float min = 0.05f;
+ float max = 4.6f;
+ float a = (1.7f - min) / (max - min);
+ assertEquals(scheme.findColour('A', 0, null), new Color(0, 1 - a, a));
+
+ float d = (0.4f - min) / (max - min);
+ assertEquals(scheme.findColour('D', 0, null), new Color(0, 1 - d, d));
+
+ assertEquals(scheme.findColour('-', 0, null), Color.WHITE);
+ }
+
+}
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;
}
@Test(groups = { "Functional" })
- public void testIsColored_simpleColour()
- {
- FeatureColour fc = new FeatureColour(Color.RED);
- assertTrue(fc
- .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
- }
-
- @Test(groups = { "Functional" })
- public void testIsColored_colourByLabel()
- {
- FeatureColour fc = new FeatureColour();
- fc.setColourByLabel(true);
- assertTrue(fc
- .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
- }
-
- @Test(groups = { "Functional" })
- public void testIsColored_aboveThreshold()
- {
- // graduated colour range from score 20 to 100
- FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f,
- 100f);
-
- // score 0 is adjusted to bottom of range
- SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f,
- null);
- assertTrue(fc.isColored(sf));
- assertEquals(Color.WHITE, fc.getColor(sf));
-
- // score 120 is adjusted to top of range
- sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
- sf.getFeatureGroup(), 120f);
- assertEquals(Color.BLACK, fc.getColor(sf));
-
- // value below threshold is still rendered
- // setting threshold has no effect yet...
- fc.setThreshold(60f);
- sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
- sf.getFeatureGroup(), 36f);
- assertTrue(fc.isColored(sf));
- assertEquals(new Color(204, 204, 204), fc.getColor(sf));
-
- // now apply threshold:
- fc.setAboveThreshold(true);
- assertFalse(fc.isColored(sf));
- // colour is still returned though ?!?
- assertEquals(new Color(204, 204, 204), fc.getColor(sf));
-
- sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
- sf.getFeatureGroup(), 84f);
- // above threshold now
- assertTrue(fc.isColored(sf));
- assertEquals(new Color(51, 51, 51), fc.getColor(sf));
- }
-
- @Test(groups = { "Functional" })
public void testGetColor_simpleColour()
{
FeatureColour fc = new FeatureColour(Color.RED);
}
@Test(groups = { "Functional" })
- public void testGetColor_belowThreshold()
+ public void testGetColor_aboveBelowThreshold()
{
// gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0)
FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f,
150f);
SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f,
null);
+
+ /*
+ * feature with score of Float.NaN is always assigned minimum colour
+ */
+ SequenceFeature sf2 = new SequenceFeature("type", "desc", 0, 20,
+ Float.NaN, null);
+
fc.setThreshold(100f); // ignore for now
- assertTrue(fc.isColored(sf));
assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+ assertEquals(Color.white, fc.getColor(sf2));
fc.setAboveThreshold(true); // feature lies below threshold
- assertFalse(fc.isColored(sf));
- assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+ assertNull(fc.getColor(sf));
+ assertEquals(Color.white, fc.getColor(sf2));
+
+ fc.setBelowThreshold(true);
+ fc.setThreshold(70f);
+ assertNull(fc.getColor(sf)); // feature score == threshold - hidden
+ assertEquals(Color.white, fc.getColor(sf2));
+ fc.setThreshold(69f);
+ assertNull(fc.getColor(sf)); // feature score > threshold - hidden
+ assertEquals(Color.white, fc.getColor(sf2));
}
/**
--- /dev/null
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class HelixColourSchemeTest
+{
+ /**
+ * Turn colours are based on the scores in ResidueProperties.helix A = 1.42, R
+ * = 0.98, N = 0.67, D = 1.01... min = 0.57 max = 1.51
+ * <p>
+ * scores are scaled to c 0-1 between min and max and colour is (c, 1-c, c)
+ */
+ @Test(groups = "Functional")
+ public void testFindColour()
+ {
+ ScoreColourScheme scheme = new HelixColourScheme();
+
+ float min = 0.57f;
+ float max = 1.51f;
+ float a = (1.42f - min) / (max - min);
+ assertEquals(scheme.findColour('A', 0, null), new Color(a, 1 - a, a));
+
+ float d = (1.01f - min) / (max - min);
+ assertEquals(scheme.findColour('D', 0, null), new Color(d, 1 - d, d));
+
+ assertEquals(scheme.findColour('-', 0, null), Color.WHITE);
+ }
+
+}
--- /dev/null
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class HydrophobicColourSchemeTest
+{
+ /**
+ * Turn colours are based on the scores in ResidueProperties.hyd A = 1.8, R =
+ * -4.5, N = -3.5, D = -3.5... min = -3.9 max = 4.5
+ * <p>
+ * scores are scaled to c 0-1 between min and max and colour is (c, 0, 1-c)
+ */
+ @Test(groups = "Functional")
+ public void testFindColour()
+ {
+ ScoreColourScheme scheme = new HydrophobicColourScheme();
+
+ float min = -3.9f;
+ float max = 4.5f;
+ float a = (1.8f - min) / (max - min);
+ assertEquals(scheme.findColour('A', 0, null),
+ new Color(a, 0, 1 - a));
+
+ float d = (-3.5f - min) / (max - min);
+ assertEquals(scheme.findColour('D', 0, null),
+ new Color(d, 0, 1 - d));
+
+ assertEquals(scheme.findColour('-', 0, null), Color.WHITE);
+ }
+
+}
--- /dev/null
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class StrandColourSchemeTest
+{
+ /**
+ * Turn colours are based on the scores in ResidueProperties.strand A = 0.83,
+ * R = 0.93, N = 0.89, D = 0.54... min = 0.37 max = 1.7
+ * <p>
+ * scores are scaled to c 0-1 between min and max and colour is (c, c, 1-c)
+ */
+ @Test(groups = "Functional")
+ public void testFindColour()
+ {
+ ScoreColourScheme scheme = new StrandColourScheme();
+
+ float min = 0.37f;
+ float max = 1.7f;
+ float a = (0.83f - min) / (max - min);
+ assertEquals(scheme.findColour('A', 0, null),
+ new Color(a, a, 1 - a));
+
+ float d = (0.54f - min) / (max - min);
+ assertEquals(scheme.findColour('D', 0, null),
+ new Color(d, d, 1 - d));
+
+ assertEquals(scheme.findColour('-', 0, null), Color.WHITE);
+ }
+
+}
--- /dev/null
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class TurnColourSchemeTest
+{
+ /**
+ * Turn colours are based on the scores in ResidueProperties.turn A = 0.66, R
+ * = 0.95, N = 1.56, D = 1.46... min = 0.47 max = 1.56
+ * <p>
+ * scores are scaled to c 0-1 between min and max and colour is (c, 1-c, 1-c)
+ */
+ @Test(groups = "Functional")
+ public void testFindColour()
+ {
+ ScoreColourScheme scheme = new TurnColourScheme();
+
+ float min = 0.47f;
+ float max = 1.56f;
+ float a = (0.66f - min) / (max - min);
+ assertEquals(scheme.findColour('A', 0, null),
+ new Color(a, 1 - a, 1 - a));
+
+ float d = (1.46f - min) / (max - min);
+ assertEquals(scheme.findColour('D', 0, null),
+ new Color(d, 1 - d, 1 - d));
+
+ assertEquals(scheme.findColour('-', 0, null), Color.WHITE);
+ }
+
+}
assertEquals(c1, cs.findColour('h'));
Color c2 = new Color(10, 20, 30);
assertEquals(c2, cs.findColour('c'));
+ assertEquals(Color.WHITE, cs.findColour('G'));
+ assertEquals(Color.WHITE, cs.findColour('-'));
+ assertEquals(Color.WHITE, cs.findColour('.'));
+ assertEquals(Color.WHITE, cs.findColour(' '));
cs = new UserColourScheme("white");
cs.parseAppletParameter("D,E=red; K,R,H=0022FF; c=10 , 20,30;t=orange;lowercase=blue;s=pink");
String param = cs.toAppletParameter();
assertEquals("D,E=ff0000;H,K,R=0022ff;c=0a141e", param);
}
+
+ /**
+ * Test for user colour scheme constructed with a colour per residue,
+ * including gap. Note this can currently be done from the User Defined
+ * Colours dialog, but not by parsing a colours parameter, as
+ * parseAppletParameter only recognises amino acid codes.
+ */
+ @Test(groups = "Functional")
+ public void testConstructor_coloursArray()
+ {
+ Color g = Color.green;
+ Color y = Color.yellow;
+ Color b = Color.blue;
+ Color r = Color.red;
+ // colours for ARNDCQEGHILKMFPSTWYVBZ and gap
+ Color[] colours = new Color[] { g, y, b, r, g, y, r, b, g, y, r, b, g,
+ y, r, b, g, y, r, b, g, y, r, g };
+ UserColourScheme cs = new UserColourScheme(colours);
+
+ assertEquals(g, cs.findColour('A'));
+ assertEquals(b, cs.findColour('n'));
+ assertEquals(g, cs.findColour('-'));
+ assertEquals(g, cs.findColour('.'));
+ assertEquals(g, cs.findColour(' '));
+ }
}
AlignedCodonFrame acf3 = new AlignedCodonFrame();
acf3.addMap(seq3.getDatasetSequence(), seq1.getDatasetSequence(), map);
- List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
+ List<AlignedCodonFrame> mappings = new ArrayList<>();
mappings.add(acf1);
mappings.add(acf2);
mappings.add(acf3);
AlignedCodonFrame acf4 = new AlignedCodonFrame();
acf4.addMap(seq3.getDatasetSequence(), seq4.getDatasetSequence(), map);
- List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
+ List<AlignedCodonFrame> mappings = new ArrayList<>();
mappings.add(acf1);
mappings.add(acf2);
mappings.add(acf3);
AlignedCodonFrame acf = new AlignedCodonFrame();
MapList map = new MapList(new int[] { 8, 16 }, new int[] { 5, 7 }, 3, 1);
acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
- List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
+ List<AlignedCodonFrame> mappings = new ArrayList<>();
mappings.add(acf);
AlignmentI prot = new Alignment(new SequenceI[] { protein });
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
assertEquals("[]", dnaSelection.getSelected().toString());
- List<int[]> hidden = dnaHidden.getHiddenRegions();
+ List<int[]> hidden = dnaHidden.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[0, 4]", Arrays.toString(hidden.get(0)));
proteinSelection.hideSelectedColumns(1, hiddenCols);
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
- hidden = dnaHidden.getHiddenRegions();
+ hidden = dnaHidden.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
proteinSelection.hideSelectedColumns(2, hiddenCols);
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
- assertTrue(dnaHidden.getHiddenRegions().isEmpty());
+ assertTrue(dnaHidden.getHiddenColumnsCopy().isEmpty());
/*
* Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
assertEquals("[0, 1, 2, 3]", dnaSelection.getSelected().toString());
- hidden = dnaHidden.getHiddenRegions();
+ hidden = dnaHidden.getHiddenColumnsCopy();
assertEquals(1, hidden.size());
assertEquals("[5, 10]", Arrays.toString(hidden.get(0)));
proteinSelection.hideSelectedColumns(3, hiddenCols);
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
- hidden = dnaHidden.getHiddenRegions();
+ hidden = dnaHidden.getHiddenColumnsCopy();
assertEquals(2, hidden.size());
assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
assertEquals("[5, 10]", Arrays.toString(hidden.get(1)));
/*
* [start, end] ranges
*/
- List<int[]> ranges = new ArrayList<int[]>();
+ List<int[]> ranges = new ArrayList<>();
assertEquals(0, MappingUtils.getLength(ranges));
ranges.add(new int[] { 1, 1 });
assertEquals(1, MappingUtils.getLength(ranges));
public void testContains()
{
assertFalse(MappingUtils.contains(null, 1));
- List<int[]> ranges = new ArrayList<int[]>();
+ List<int[]> ranges = new ArrayList<>();
assertFalse(MappingUtils.contains(ranges, 1));
ranges.add(new int[] { 1, 4 });
package jalview.viewmodel;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import jalview.analysis.AlignmentGenerator;
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);
}
@Test(groups = { "Functional" })
public void testScrollToWrappedVisible()
{
- ViewportRanges vr = new ViewportRanges(al);
+ AlignmentI al2 = gen.generate(60, 30, 1, 5, 5);
+
+ ViewportRanges vr = new ViewportRanges(al2);
+
+ // start with viewport on 5-14
vr.setViewportStartAndWidth(5, 10);
+ assertEquals(vr.getStartRes(), 5);
+ assertEquals(vr.getEndRes(), 14);
+
+ // scroll to 12 - no change
+ assertFalse(vr.scrollToWrappedVisible(12));
+ assertEquals(vr.getStartRes(), 5);
- vr.scrollToWrappedVisible(0);
+ // scroll to 2 - back to 0-9
+ assertTrue(vr.scrollToWrappedVisible(2));
assertEquals(vr.getStartRes(), 0);
+ assertEquals(vr.getEndRes(), 9);
- vr.scrollToWrappedVisible(10);
- assertEquals(vr.getStartRes(), 10);
+ // scroll to 9 - no change
+ assertFalse(vr.scrollToWrappedVisible(9));
+ assertEquals(vr.getStartRes(), 0);
- vr.scrollToWrappedVisible(15);
+ // scroll to 12 - moves to 10-19
+ assertTrue(vr.scrollToWrappedVisible(12));
assertEquals(vr.getStartRes(), 10);
+ assertEquals(vr.getEndRes(), 19);
+
+ vr.setStartRes(13);
+ assertEquals(vr.getStartRes(), 13);
+ assertEquals(vr.getEndRes(), 22);
+
+ // scroll to 45 - jumps to 43-52
+ assertTrue(vr.scrollToWrappedVisible(45));
+ assertEquals(vr.getStartRes(), 43);
+ assertEquals(vr.getEndRes(), 52);
}
// leave until JAL-2388 is merged and we can do without viewport
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
<string><![CDATA[664]]></string>
</property>
<property name="sourceName">
- <string><![CDATA[min-jabaws-client-2.1.0.jar]]></string>
+ <string><![CDATA[jabaws-min-client-2.2.0.jar]]></string>
</property>
<property name="overrideUnixPermissions">
<boolean>false</boolean>