createAlignFrameWindow(embedded);
validate();
alignPanel.adjustAnnotationHeight();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
public AlignViewport getAlignViewport()
{
viewport.featureSettings.refreshTable();
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
statusBar.setText(MessageManager
.getString("label.successfully_added_features_alignment"));
}
break;
}
- alignPanel.paintAlignment(true);
+ // TODO: repaint flags set only if the keystroke warrants it
+ alignPanel.paintAlignment(true, true);
}
/**
{
applyAutoAnnotationSettings_actionPerformed();
}
- alignPanel.paintAlignment(true);
+ // TODO: repaint flags set only if warranted
+ alignPanel.paintAlignment(true, true);
}
/**
else if (source == invertColSel)
{
viewport.invertColumnSelection();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
viewport.sendSelection();
}
else if (source == remove2LeftMenuItem)
else if (source == showColumns)
{
viewport.showAllHiddenColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == showSeqs)
{
viewport.showAllHiddenSeqs();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
// uncomment if we want to slave sequence selections in split frame
// viewport.sendSelection();
}
else if (source == hideColumns)
{
viewport.hideSelectedColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == hideSequences
&& viewport.getSelectionGroup() != null)
{
viewport.hideAllSelectedSeqs();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
// uncomment if we want to slave sequence selections in split frame
// viewport.sendSelection();
}
else if (source == hideAllButSelection)
{
toggleHiddenRegions(false, false);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == hideAllSelection)
viewport.expandColSelection(sg, false);
viewport.hideAllSelectedSeqs();
viewport.hideSelectedColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == showAllHidden)
{
viewport.showAllHiddenColumns();
viewport.showAllHiddenSeqs();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == showGroupConsensus)
{
System.exit(0);
}
- else
+
+ viewport = null;
+ if (alignPanel != null && alignPanel.overviewPanel != null)
{
+ alignPanel.overviewPanel.dispose();
}
- viewport = null;
alignPanel = null;
this.dispose();
}
}
viewport.getAlignment().moveSelectedSequencesByOne(sg,
up ? null : viewport.getHiddenRepSequences(), up);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
/*
* Also move cDNA/protein complement sequences
viewport, complement);
complement.getAlignment().moveSelectedSequencesByOne(mappedSelection,
up ? null : complement.getHiddenRepSequences(), up);
- getSplitFrame().getComplement(this).alignPanel.paintAlignment(true);
+ getSplitFrame().getComplement(this).alignPanel.paintAlignment(true,
+ false);
}
}
static StringBuffer copiedSequences;
- static Vector<int[]> copiedHiddenColumns;
+ static HiddenColumns copiedHiddenColumns;
protected void copy_actionPerformed()
{
if (viewport.hasHiddenColumns() && viewport.getSelectionGroup() != null)
{
- copiedHiddenColumns = new Vector<>(viewport.getAlignment()
- .getHiddenColumns().getHiddenColumnsCopy());
int hiddenOffset = viewport.getSelectionGroup().getStartRes();
- for (int[] region : copiedHiddenColumns)
- {
- region[0] = region[0] - hiddenOffset;
- region[1] = region[1] - hiddenOffset;
- }
+ int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
+
+ // create new HiddenColumns object with copy of hidden regions
+ // between startRes and endRes, offset by startRes
+ copiedHiddenColumns = new HiddenColumns(
+ viewport.getAlignment().getHiddenColumns(), hiddenOffset,
+ hiddenCutoff, hiddenOffset);
}
else
{
}
AlignFrame af = new AlignFrame(new Alignment(newSeqs),
viewport.applet, newtitle, false);
- if (copiedHiddenColumns != null)
- {
- for (int i = 0; i < copiedHiddenColumns.size(); i++)
- {
- int[] region = copiedHiddenColumns.elementAt(i);
- af.viewport.hideColumns(region[0], region[1]);
- }
- }
+ af.viewport.setHiddenColumns(copiedHiddenColumns);
jalview.bin.JalviewLite.addFrame(af, newtitle, frameWidth,
frameHeight);
{
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
alignPanel.updateAnnotation();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
public void invertColSel_actionPerformed()
{
viewport.invertColumnSelection();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
{
viewport.setShowJVSuffix(seqLimits.getState());
alignPanel.fontChanged();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
protected void colourTextMenuItem_actionPerformed()
{
viewport.setColourText(colourTextMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
protected void displayNonconservedMenuItem_actionPerformed()
{
viewport.setShowUnconserved(displayNonconservedMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
protected void wrapMenuItem_actionPerformed()
scaleAbove.setEnabled(wrapMenuItem.getState());
scaleLeft.setEnabled(wrapMenuItem.getState());
scaleRight.setEnabled(wrapMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
public void overviewMenuItem_actionPerformed()
{
viewport.setGlobalColourScheme(cs);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
protected void modifyPID_actionPerformed()
addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
public void sortIDMenuItem_actionPerformed()
AlignmentSorter.sortByID(viewport.getAlignment());
addHistoryItem(
new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
public void sortLengthMenuItem_actionPerformed()
AlignmentSorter.sortByLength(viewport.getAlignment());
addHistoryItem(new OrderCommand("Length Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
public void sortGroupMenuItem_actionPerformed()
AlignmentSorter.sortByGroup(viewport.getAlignment());
addHistoryItem(new OrderCommand("Group Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
current.insertCharAt(Width - 1, viewport.getGapCharacter());
}
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
if ((viewport.getSelectionGroup() != null
current.insertCharAt(Width - 1, viewport.getGapCharacter());
}
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
addHistoryItem(new OrderCommand(MessageManager
.formatMessage("label.order_by_params", new String[]
{ title }), oldOrder, viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
addHistoryItem(new OrderCommand(undoname, oldOrder,
viewport.getAlignment()));
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
return true;
}
{
// register the association(s) and quit, don't create any windows.
if (StructureSelectionManager.getStructureSelectionManager(applet)
- .setMapping(seqs, chains, pdb.getFile(), protocol) == null)
+ .setMapping(seqs, chains, pdb.getFile(), protocol, null) == null)
{
System.err.println("Failed to map " + pdb.getFile() + " ("
+ protocol + ") to any sequences");
import java.awt.event.MouseListener;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
-import java.util.ArrayList;
import java.util.Vector;
//import javax.swing.JPanel;
{
HiddenColumns oldHidden = av.getAnnotationColumnSelectionState()
.getOldHiddenColumns();
av.getAlignment().setHiddenColumns(oldHidden);
}
av.sendSelection();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
sliderDragging = false;
valueChanged(true);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
});
}
if (slider.isEnabled())
{
getCurrentAnnotation().threshold.value = slider.getValue() / 1000f;
- updateView();
- ap.paintAlignment(false);
+ updateView(); // this also calls paintAlignment(true,true)
}
}
filterParams = null;
av.setAnnotationColumnSelectionState(this);
av.sendSelection();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
public HiddenColumns getOldHiddenColumns()
import jalview.analysis.AlignmentUtils;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.util.MessageManager;
import java.awt.event.MouseMotionListener;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Vector;
public class AnnotationLabels extends Panel
implements ActionListener, MouseListener, MouseMotionListener
ap.annotationPanel.adjustPanelHeight();
setSize(getSize().width, ap.annotationPanel.getSize().height);
ap.validate();
- ap.paintAlignment(true);
+ // TODO: only paint if we needed to
+ ap.paintAlignment(true, true);
}
boolean editLabelDescription(AlignmentAnnotation annotation)
{
ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
});
popup.add(cbmi);
}
}
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
sg.addSequence(aa[selectedRow].sequenceRef, false);
}
ap.av.setSelectionGroup(sg);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
+ "\t" + sq.getSequenceAsString() + "\n");
if (av.hasHiddenColumns())
{
- jalview.appletgui.AlignFrame.copiedHiddenColumns = new Vector<>(
- av.getAlignment().getHiddenColumns().getHiddenColumnsCopy());
+ jalview.appletgui.AlignFrame.copiedHiddenColumns = new HiddenColumns(
+ av.getAlignment().getHiddenColumns());
}
}
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
+import java.util.Iterator;
import java.util.List;
public class ScalePanel extends Panel
sg.setStartRes(min);
sg.setEndRes(max);
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
{
av.showColumn(reveal[0]);
reveal = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
{
av.showAllHiddenColumns();
reveal = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
av.setSelectionGroup(null);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
if (!stretchingGroup)
{
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
return;
}
}
stretchingGroup = false;
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
{
stretchingGroup = true;
cs.stretchGroup(res, sg, min, max);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
if (av.getShowHiddenMarkers())
{
int widthx = 1 + endx - startx;
- List<Integer> positions = hidden.findHiddenRegionPositions();
- for (int pos : positions)
+ Iterator<Integer> it = hidden.getBoundedStartIterator(startx,
+ startx + widthx + 1);
+ while (it.hasNext())
{
-
- res = pos - startx;
-
- if (res < 0 || res > widthx)
- {
- continue;
- }
+ res = it.next() - startx;
gg.fillPolygon(
new int[]
- { -1 + res * avCharWidth - avcharHeight / 4,
- -1 + res * avCharWidth + avcharHeight / 4,
- -1 + res * avCharWidth },
- new int[]
- { y, y, y + 2 * yOf }, 3);
+ { -1 + res * avCharWidth - avcharHeight / 4, -1 + res * avCharWidth + avcharHeight / 4,
+ -1 + res * avCharWidth }, new int[]
+ { y, y, y + 2 * yOf }, 3);
}
}
}
import java.util.ListIterator;
import java.util.Vector;
- import com.stevesoft.pat.Regex;
-
import fr.orsay.lri.varna.models.rna.RNA;
/**
*/
public class Sequence extends ASequence implements SequenceI
{
- private static final Regex limitrx = new Regex(
- "[/][0-9]{1,}[-][0-9]{1,}$");
-
- private static final Regex endrx = new Regex("[0-9]{1,}$");
-
SequenceI datasetSequence;
String name;
*/
int index = -1;
- private SequenceFeatures sequenceFeatureStore;
+ private SequenceFeaturesI sequenceFeatureStore;
/*
* A cursor holding the approximate current view position to the sequence,
checkValidRange();
}
+ /**
+ * If 'name' ends in /i-j, where i >= j > 0 are integers, extracts i and j as
+ * start and end respectively and removes the suffix from the name
+ */
void parseId()
{
if (name == null)
"POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor.");
name = "";
}
- // Does sequence have the /start-end signature?
- if (limitrx.search(name))
+ int slashPos = name.lastIndexOf('/');
+ if (slashPos > -1 && slashPos < name.length() - 1)
{
- name = limitrx.left();
- endrx.search(limitrx.stringMatched());
- setStart(Integer.parseInt(limitrx.stringMatched().substring(1,
- endrx.matchedFrom() - 1)));
- setEnd(Integer.parseInt(endrx.stringMatched()));
+ String suffix = name.substring(slashPos + 1);
+ String[] range = suffix.split("-");
+ if (range.length == 2)
+ {
+ try
+ {
+ int from = Integer.valueOf(range[0]);
+ int to = Integer.valueOf(range[1]);
+ if (from > 0 && to >= from)
+ {
+ name = name.substring(0, slashPos);
+ setStart(from);
+ setEnd(to);
+ checkValidRange();
+ }
+ } catch (NumberFormatException e)
+ {
+ // leave name unchanged if suffix is invalid
+ }
+ }
}
}
+ /**
+ * Ensures that 'end' is not before the end of the sequence, that is,
+ * (end-start+1) is at least as long as the count of ungapped positions. Note
+ * that end is permitted to be beyond the end of the sequence data.
+ */
void checkValidRange()
{
// Note: JAL-774 :
int endRes = 0;
for (int j = 0; j < sequence.length; j++)
{
- if (!jalview.util.Comparison.isGap(sequence[j]))
+ if (!Comparison.isGap(sequence[j]))
{
endRes++;
}
{
if (pdbIds == null)
{
- pdbIds = new Vector<PDBEntry>();
+ pdbIds = new Vector<>();
pdbIds.add(entry);
return true;
}
}
/**
- * DOCUMENT ME!
+ * Sets the sequence name. If the name ends in /start-end, then the start-end
+ * values are parsed out and set, and the suffix is removed from the name.
*
- * @param name
- * DOCUMENT ME!
+ * @param theName
*/
@Override
- public void setName(String name)
+ public void setName(String theName)
{
- this.name = name;
+ this.name = theName;
this.parseId();
}
return map;
}
+ /**
+ * Build a bitset corresponding to sequence gaps
+ *
+ * @return a BitSet where set values correspond to gaps in the sequence
+ */
+ @Override
+ public BitSet gapBitset()
+ {
+ BitSet gaps = new BitSet(sequence.length);
+ int j = 0;
+ while (j < sequence.length)
+ {
+ if (jalview.util.Comparison.isGap(sequence[j]))
+ {
+ gaps.set(j);
+ }
+ j++;
+ }
+ return gaps;
+ }
+
@Override
public int[] findPositionMap()
{
@Override
public List<int[]> getInsertions()
{
- ArrayList<int[]> map = new ArrayList<int[]>();
+ ArrayList<int[]> map = new ArrayList<>();
int lastj = -1, j = 0;
int pos = start;
int seqlen = sequence.length;
{
if (this.annotation == null)
{
- this.annotation = new Vector<AlignmentAnnotation>();
+ this.annotation = new Vector<>();
}
if (!this.annotation.contains(annotation))
{
return null;
}
- Vector<AlignmentAnnotation> subset = new Vector<AlignmentAnnotation>();
+ Vector<AlignmentAnnotation> subset = new Vector<>();
Enumeration<AlignmentAnnotation> e = annotation.elements();
while (e.hasMoreElements())
{
public List<AlignmentAnnotation> getAlignmentAnnotations(String calcId,
String label)
{
- List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+ List<AlignmentAnnotation> result = new ArrayList<>();
if (this.annotation != null)
{
for (AlignmentAnnotation ann : annotation)
}
synchronized (dbrefs)
{
- List<DBRefEntry> primaries = new ArrayList<DBRefEntry>();
+ List<DBRefEntry> primaries = new ArrayList<>();
DBRefEntry[] tmp = new DBRefEntry[1];
for (DBRefEntry ref : dbrefs)
{
* and we may have included adjacent or enclosing features;
* remove any that are not enclosing, non-contact features
*/
- if (endPos > this.end || Comparison.isGap(sequence[toColumn - 1]))
+ boolean endColumnIsGapped = toColumn > 0 && toColumn <= sequence.length
+ && Comparison.isGap(sequence[toColumn - 1]);
+ if (endPos > this.end || endColumnIsGapped)
{
ListIterator<SequenceFeature> it = result.listIterator();
while (it.hasNext())
AlignViewport viewport;
- ViewportRanges vpRanges;
-
public AlignViewControllerI avc;
List<AlignmentPanel> alignPanels = new ArrayList<>();
progressBar = new ProgressBar(this.statusPanel, this.statusBar);
}
- vpRanges = viewport.getRanges();
avc = new jalview.controller.AlignViewController(this, viewport,
alignPanel);
if (viewport.getAlignmentConservationAnnotation() == null)
{ (viewport.cursorMode ? "on" : "off") }));
if (viewport.cursorMode)
{
- alignPanel.getSeqPanel().seqCanvas.cursorX = vpRanges
+ ViewportRanges ranges = viewport.getRanges();
+ alignPanel.getSeqPanel().seqCanvas.cursorX = ranges
.getStartRes();
- alignPanel.getSeqPanel().seqCanvas.cursorY = vpRanges
+ alignPanel.getSeqPanel().seqCanvas.cursorY = ranges
.getStartSeq();
}
alignPanel.getSeqPanel().seqCanvas.repaint();
break;
}
case KeyEvent.VK_PAGE_UP:
- vpRanges.pageUp();
+ viewport.getRanges().pageUp();
break;
case KeyEvent.VK_PAGE_DOWN:
- vpRanges.pageDown();
+ viewport.getRanges().pageDown();
break;
}
}
}
viewport.getAlignment().moveSelectedSequencesByOne(sg,
viewport.getHiddenRepSequences(), up);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
synchronized void slideSequences(boolean right, int size)
return;
}
- ArrayList<int[]> hiddenColumns = null;
+ HiddenColumns hiddenColumns = null;
if (viewport.hasHiddenColumns())
{
- 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)
- {
- hiddenColumns
- .add(new int[]
- { region[0] - hiddenOffset, region[1] - hiddenOffset });
- }
- }
+
+ // create new HiddenColumns object with copy of hidden regions
+ // between startRes and endRes, offset by startRes
+ hiddenColumns = new HiddenColumns(
+ viewport.getAlignment().getHiddenColumns(), hiddenOffset,
+ hiddenCutoff, hiddenOffset);
}
Desktop.jalviewClipboard = new Object[] { seqs,
{
// propagate alignment changed.
- vpRanges.setEndSeq(alignment.getHeight());
+ viewport.getRanges().setEndSeq(alignment.getHeight());
if (annotationAdded)
{
// Duplicate sequence annotation in all views.
if (Desktop.jalviewClipboard != null
&& Desktop.jalviewClipboard[2] != null)
{
- List<int[]> hc = (List<int[]>) Desktop.jalviewClipboard[2];
- for (int[] region : hc)
- {
- af.viewport.hideColumns(region[0], region[1]);
- }
+ HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
+ af.viewport.setHiddenColumns(hc);
}
// >>>This is a fix for the moment, until a better solution is
if (Desktop.jalviewClipboard != null
&& Desktop.jalviewClipboard[2] != null)
{
- List<int[]> hc = (List<int[]>) Desktop.jalviewClipboard[2];
- for (int region[] : hc)
- {
- af.viewport.hideColumns(region[0], region[1]);
- }
+ HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
+ af.viewport.setHiddenColumns(hc);
}
// >>>This is a fix for the moment, until a better solution is
{
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
alignPanel.updateAnnotation();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
}
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
public void invertColSel_actionPerformed(ActionEvent e)
{
viewport.invertColumnSelection();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
viewport.sendSelection();
}
{
trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
column, viewport.getAlignment());
- vpRanges.setStartRes(0);
+ viewport.getRanges().setStartRes(0);
}
else
{
// This is to maintain viewport position on first residue
// of first sequence
SequenceI seq = viewport.getAlignment().getSequenceAt(0);
- int startRes = seq.findPosition(vpRanges.getStartRes());
+ ViewportRanges ranges = viewport.getRanges();
+ int startRes = seq.findPosition(ranges.getStartRes());
// ShiftList shifts;
// viewport.getAlignment().removeGaps(shifts=new ShiftList());
// edit.alColumnChanges=shifts.getInverse();
// if (viewport.hasHiddenColumns)
// viewport.getColumnSelection().compensateForEdits(shifts);
- vpRanges.setStartRes(seq.findIndex(startRes) - 1);
+ ranges.setStartRes(seq.findIndex(startRes) - 1);
viewport.firePropertyChange("alignment", null,
viewport.getAlignment().getSequences());
// This is to maintain viewport position on first residue
// of first sequence
SequenceI seq = viewport.getAlignment().getSequenceAt(0);
- int startRes = seq.findPosition(vpRanges.getStartRes());
+ int startRes = seq.findPosition(viewport.getRanges().getStartRes());
addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
viewport.getAlignment()));
- vpRanges.setStartRes(seq.findIndex(startRes) - 1);
+ viewport.getRanges().setStartRes(seq.findIndex(startRes) - 1);
viewport.firePropertyChange("alignment", null,
viewport.getAlignment().getSequences());
/*
* Create a new AlignmentPanel (with its own, new Viewport)
*/
- AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel,
- true);
+ AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel);
if (!copyAnnotation)
{
/*
alignPanel.getIdPanel().getIdCanvas()
.setPreferredSize(alignPanel.calculateIdWidth());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
@Override
public void idRightAlign_actionPerformed(ActionEvent e)
{
viewport.setRightAlignIds(idRightAlign.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
@Override
public void centreColumnLabels_actionPerformed(ActionEvent e)
{
viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/*
protected void colourTextMenuItem_actionPerformed(ActionEvent e)
{
viewport.setColourText(colourTextMenuItem.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/**
public void showAllColumns_actionPerformed(ActionEvent e)
{
viewport.showAllHiddenColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
viewport.expandColSelection(sg, false);
viewport.hideAllSelectedSeqs();
viewport.hideSelectedColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
{
viewport.showAllHiddenColumns();
viewport.showAllHiddenSeqs();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
public void hideSelColumns_actionPerformed(ActionEvent e)
{
viewport.hideSelectedColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
protected void scaleAbove_actionPerformed(ActionEvent e)
{
viewport.setScaleAboveWrapped(scaleAbove.isSelected());
- alignPanel.paintAlignment(true);
+ // TODO: do we actually need to update overview for scale above change ?
+ alignPanel.paintAlignment(true, false);
}
/**
protected void scaleLeft_actionPerformed(ActionEvent e)
{
viewport.setScaleLeftWrapped(scaleLeft.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
protected void scaleRight_actionPerformed(ActionEvent e)
{
viewport.setScaleRightWrapped(scaleRight.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
{
viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/**
public void viewTextMenuItem_actionPerformed(ActionEvent e)
{
viewport.setShowText(viewTextMenuItem.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/**
protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
{
viewport.setRenderGaps(renderGapsMenuItem.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
public FeatureSettings featureSettings;
public void showSeqFeatures_actionPerformed(ActionEvent evt)
{
viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
/**
viewport.setGlobalColourScheme(cs);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
/**
viewport.getAlignment().getSequenceAt(0));
addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
AlignmentSorter.sortByID(viewport.getAlignment());
addHistoryItem(
new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
AlignmentSorter.sortByLength(viewport.getAlignment());
addHistoryItem(new OrderCommand("Length Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
addHistoryItem(new OrderCommand("Group Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
addHistoryItem(new OrderCommand(order.getName(), oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
});
}
viewport.getAlignment());// ,viewport.getSelectionGroup());
addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
});
}
addHistoryItem(new OrderCommand(undoname, oldOrder,
viewport.getAlignment()));
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
return true;
}
assocfiles++;
}
}
- alignPanel.paintAlignment(true);
+ // TODO: do we need to update overview ? only if features are
+ // shown I guess
+ alignPanel.paintAlignment(true, false);
}
}
}
{
if (parseFeaturesFile(file, sourceType))
{
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
else
alignPanel.adjustAnnotationHeight();
viewport.updateSequenceIdColours();
buildSortByAnnotationScoresMenu();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
} catch (Exception ex)
{
protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
{
viewport.setShowUnconserved(showNonconservedMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/*
{
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
alignPanel.updateAnnotation();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
viewport.getAlignment().setSeqrep(null);
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
alignPanel.updateAnnotation();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
this.alignPanel.av
.setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/**
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.List;
import java.util.Vector;
{
Font font;
- TreeModel currentTree = null;
-
boolean cursorMode = false;
boolean antiAlias = false;
}
/**
- * DOCUMENT ME!
- *
- * @param tree
- * DOCUMENT ME!
- */
- public void setCurrentTree(TreeModel tree)
- {
- currentTree = tree;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public TreeModel getCurrentTree()
- {
- return currentTree;
- }
-
- /**
* returns the visible column regions of the alignment
*
* @param selectedRegionOnly
* area
* @return
*/
- public int[] getViewAsVisibleContigs(boolean selectedRegionOnly)
+ public Iterator<int[]> getViewAsVisibleContigs(boolean selectedRegionOnly)
{
- int[] viscontigs = null;
- int start = 0, end = 0;
+ int start = 0;
+ int end = 0;
if (selectedRegionOnly && selectionGroup != null)
{
start = selectionGroup.getStartRes();
{
end = alignment.getWidth();
}
- viscontigs = alignment.getHiddenColumns().getVisibleContigs(start, end);
- return viscontigs;
+ return (alignment.getHiddenColumns().getVisContigsIterator(start, end));
}
/**
*/
public SequenceI[][] collateForPDB(PDBEntry[] pdbEntries)
{
- List<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
+ List<SequenceI[]> seqvectors = new ArrayList<>();
for (PDBEntry pdb : pdbEntries)
{
- List<SequenceI> choosenSeqs = new ArrayList<SequenceI>();
+ List<SequenceI> choosenSeqs = new ArrayList<>();
for (SequenceI sq : alignment.getSequences())
{
Vector<PDBEntry> pdbRefEntries = sq.getDatasetSequence()
return validCharWidth;
}
- private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<String, AutoCalcSetting>();
+ private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<>();
public AutoCalcSetting getCalcIdSettingsFor(String calcId)
{
}
fr.setTransparency(featureSettings.getTransparency());
}
-
}
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
-import java.util.ArrayList;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
{
HiddenColumns oldHidden = av.getAnnotationColumnSelectionState()
.getOldHiddenColumns();
av.getAlignment().setHiddenColumns(oldHidden);
}
av.sendSelection();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
updateView();
propagateSeqAssociatedThreshold(updateAllAnnotation,
getCurrentAnnotation());
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
av.getColumnSelection().filterAnnotations(
getCurrentAnnotation().annotations, filterParams);
- if (getActionOption() == ACTION_OPTION_HIDE)
+ boolean hideCols = getActionOption() == ACTION_OPTION_HIDE;
+ if (hideCols)
{
av.hideSelectedColumns();
}
filterParams = null;
av.setAnnotationColumnSelectionState(this);
- ap.paintAlignment(true);
+ // only update overview and structures if columns were hidden
+ ap.paintAlignment(hideCols, hideCols);
}
public HiddenColumns getOldHiddenColumns()
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.regex.Pattern;
d = ap.annotationSpaceFillerHolder.getPreferredSize();
ap.annotationSpaceFillerHolder
.setPreferredSize(new Dimension(d.width, d.height - dif));
- ap.paintAlignment(true);
+ ap.paintAlignment(true, false);
}
ap.addNotify();
}
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
sg.addSequence(aa[selectedRow].sequenceRef, false);
}
ap.av.setSelectionGroup(sg);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
Toolkit.getDefaultToolkit().getSystemClipboard()
.setContents(new StringSelection(output), Desktop.instance);
- ArrayList<int[]> hiddenColumns = null;
+ HiddenColumns hiddenColumns = null;
if (av.hasHiddenColumns())
{
- hiddenColumns = av.getAlignment().getHiddenColumns()
- .getHiddenColumnsCopy();
+ hiddenColumns = new HiddenColumns(
+ av.getAlignment().getHiddenColumns());
}
Desktop.jalviewClipboard = new Object[] { seqs, ds, // what is the dataset
}
}
- void clearSeqRefs()
- {
- if (_cleartables)
- {
- if (seqRefIds != null)
- {
- seqRefIds.clear();
- }
- if (seqsToIds != null)
- {
- seqsToIds.clear();
- }
- if (incompleteSeqs != null)
- {
- incompleteSeqs.clear();
- }
- // seqRefIds = null;
- // seqsToIds = null;
- }
- else
- {
- // do nothing
- warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
- // seqRefIds = new Hashtable();
- // seqsToIds = new IdentityHashMap();
- }
- }
-
void initSeqRefs()
{
if (seqsToIds == null)
// SAVE TREES
// /////////////////////////////////
- if (!storeDS && av.currentTree != null)
+ if (!storeDS && av.getCurrentTree() != null)
{
// FIND ANY ASSOCIATED TREES
// NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
{
Tree tree = new Tree();
tree.setTitle(tp.getTitle());
- tree.setCurrentTree((av.currentTree == tp.getTree()));
+ tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
tree.setNewick(tp.getTree().print());
tree.setThreshold(tp.treeCanvas.threshold);
}
else
{
- ArrayList<int[]> hiddenRegions = hidden.getHiddenColumnsCopy();
- for (int[] region : hiddenRegions)
+ Iterator<int[]> hiddenRegions = hidden.iterator();
+ while (hiddenRegions.hasNext())
{
+ int[] region = hiddenRegions.next();
HiddenColumns hc = new HiddenColumns();
hc.setStart(region[0]);
hc.setEnd(region[1]);
jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
af = loadJalviewAlign(jprovider);
+ af.setMenusForViewport();
} catch (MalformedURLException e)
{
StructureData filedat = oldFiles.get(id);
String pdbFile = filedat.getFilePath();
SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
- binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
+ binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
+ null);
binding.addSequenceForStructFile(pdbFile, seq);
}
// and add the AlignmentPanel's reference to the view panel
}
- public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
- boolean keepSeqRefs)
+ /**
+ * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
+ * view as XML (but not to file), and then reloading it
+ *
+ * @param ap
+ * @return
+ */
+ public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
{
initSeqRefs();
JalviewModel jm = saveState(ap, null, null, null);
- if (!keepSeqRefs)
- {
- clearSeqRefs();
- jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
- }
- else
- {
- uniqueSetSuffix = "";
- jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
- // overwrite the
- // view we just
- // copied
- }
+ uniqueSetSuffix = "";
+ jm.getJalviewModelSequence().getViewport(0).setId(null);
+ // we don't overwrite the view we just copied
+
if (this.frefedSequence == null)
{
- frefedSequence = new Vector();
+ frefedSequence = new Vector<SeqFref>();
}
viewportsAdded.clear();
return af.alignPanel;
}
- /**
- * flag indicating if hashtables should be cleared on finalization TODO this
- * flag may not be necessary
- */
- private final boolean _cleartables = true;
-
private Hashtable jvids2vobj;
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#finalize()
- */
- @Override
- protected void finalize() throws Throwable
- {
- // really make sure we have no buried refs left.
- if (_cleartables)
- {
- clearSeqRefs();
- }
- this.seqRefIds = null;
- this.seqsToIds = null;
- super.finalize();
- }
-
private void warn(String msg)
{
warn(msg, null);
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
+import java.util.Iterator;
import java.util.List;
import javax.swing.JMenuItem;
{
av.showColumn(reveal[0]);
reveal = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
pop.add(item);
- if (av.getAlignment().getHiddenColumns().hasHiddenColumns())
+ if (av.getAlignment().getHiddenColumns().hasManyHiddenColumns())
{
item = new JMenuItem(MessageManager.getString("action.reveal_all"));
item.addActionListener(new ActionListener()
{
av.showAllHiddenColumns();
reveal = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
av.setSelectionGroup(null);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
sg.setEndRes(max);
}
av.setSelectionGroup(sg);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
}
else
{
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
return;
}
}
}
stretchingGroup = false;
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
{
stretchingGroup = true;
cs.stretchGroup(res, sg, min, max);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
if (av.getShowHiddenMarkers())
{
- List<Integer> positions = hidden.findHiddenRegionPositions();
- for (int pos : positions)
+ Iterator<Integer> it = hidden.getBoundedStartIterator(startx,
+ startx + widthx + 1);
+ while (it.hasNext())
{
- res = pos - startx;
-
- if (res < 0 || res > widthx)
- {
- continue;
- }
+ res = it.next() - startx;
gg.fillPolygon(
new int[]
- { -1 + res * avCharWidth - avCharHeight / 4,
- -1 + res * avCharWidth + avCharHeight / 4,
- -1 + res * avCharWidth },
- new int[]
- { y, y, y + 2 * yOf }, 3);
+ { -1 + res * avCharWidth - avCharHeight / 4,
+ -1 + res * avCharWidth + avCharHeight / 4,
+ -1 + res * avCharWidth }, new int[]
+ { y, y, y + 2 * yOf }, 3);
}
}
}
import jalview.datamodel.AlignmentI;
import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenColumns.VisibleBlocksVisBoundsIterator;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.renderer.ScaleRenderer;
import jalview.renderer.ScaleRenderer.ScaleMark;
+ import jalview.util.Comparison;
import jalview.viewmodel.ViewportListenerI;
import jalview.viewmodel.ViewportRanges;
import java.awt.Shape;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
+import java.util.Iterator;
+ import java.util.List;
import javax.swing.JComponent;
/**
- * DOCUMENT ME!
+ * The Swing component on which the alignment sequences, and annotations (if
+ * shown), are drawn. This includes scales above, left and right (if shown) in
+ * Wrapped mode, but not the scale above in Unwrapped mode.
*
*/
public class SeqCanvas extends JComponent implements ViewportListenerI
{
- private static String ZEROS = "0000000000";
+ private static final String ZEROS = "0000000000";
final FeatureRenderer fr;
- final SequenceRenderer seqRdr;
-
BufferedImage img;
- Graphics2D gg;
-
AlignViewport av;
- boolean fastPaint = false;
+ int cursorX = 0;
- int labelWidthWest;
+ int cursorY = 0;
- int labelWidthEast;
+ private final SequenceRenderer seqRdr;
- int cursorX = 0;
+ private boolean fastPaint = false;
- int cursorY = 0;
+ private boolean fastpainting = false;
- int charHeight = 0;
+ private AnnotationPanel annotations;
- int charWidth = 0;
+ /*
+ * measurements for drawing a wrapped alignment
+ */
+ private int labelWidthEast; // label right width in pixels if shown
+
+ private int labelWidthWest; // label left width in pixels if shown
- boolean fastpainting = false;
+ private int wrappedSpaceAboveAlignment; // gap between widths
- AnnotationPanel annotations;
+ private int wrappedRepeatHeightPx; // height in pixels of wrapped width
+
+ private int wrappedVisibleWidths; // number of wrapped widths displayed
+
+ private Graphics2D gg;
/**
* Creates a new SeqCanvas object.
*
- * @param av
- * DOCUMENT ME!
+ * @param ap
*/
public SeqCanvas(AlignmentPanel ap)
{
this.av = ap.av;
- updateViewport();
fr = new FeatureRenderer(ap);
seqRdr = new SequenceRenderer(av);
setLayout(new BorderLayout());
return fr;
}
- private void updateViewport()
- {
- charHeight = av.getCharHeight();
- charWidth = av.getCharWidth();
- }
-
/**
- * DOCUMENT ME!
+ * Draws the scale above a region of a wrapped alignment, consisting of a
+ * column number every major interval (10 columns).
*
* @param g
- * DOCUMENT ME!
+ * the graphics context to draw on, positioned at the start (bottom
+ * left) of the line on which to draw any scale marks
* @param startx
- * DOCUMENT ME!
+ * start alignment column (0..)
* @param endx
- * DOCUMENT ME!
+ * end alignment column (0..)
* @param ypos
- * DOCUMENT ME!
+ * y offset to draw at
*/
private void drawNorthScale(Graphics g, int startx, int endx, int ypos)
{
- updateViewport();
- for (ScaleMark mark : new ScaleRenderer().calculateMarks(av, startx,
- endx))
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
+ /*
+ * white fill the scale space (for the fastPaint case)
+ */
+ g.setColor(Color.white);
+ g.fillRect(0, ypos - charHeight - charHeight / 2, getWidth(),
+ charHeight * 3 / 2 + 2);
+ g.setColor(Color.black);
+
+ List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, startx,
+ endx);
+ for (ScaleMark mark : marks)
{
int mpos = mark.column; // (i - startx - 1)
if (mpos < 0)
{
g.drawString(mstring, mpos * charWidth, ypos - (charHeight / 2));
}
- g.drawLine((mpos * charWidth) + (charWidth / 2),
- (ypos + 2) - (charHeight / 2),
- (mpos * charWidth) + (charWidth / 2), ypos - 2);
+
+ /*
+ * draw a tick mark below the column number, centred on the column;
+ * height of tick mark is 4 pixels less than half a character
+ */
+ int xpos = (mpos * charWidth) + (charWidth / 2);
+ g.drawLine(xpos, (ypos + 2) - (charHeight / 2), xpos, ypos - 2);
}
}
}
/**
- * DOCUMENT ME!
+ * Draw the scale to the left or right of a wrapped alignment
*
* @param g
- * DOCUMENT ME!
+ * graphics context, positioned at the start of the scale to be drawn
* @param startx
- * DOCUMENT ME!
+ * first column of wrapped width (0.. excluding any hidden columns)
* @param endx
- * DOCUMENT ME!
+ * last column of wrapped width (0.. excluding any hidden columns)
* @param ypos
- * DOCUMENT ME!
+ * vertical offset at which to begin the scale
+ * @param left
+ * if true, scale is left of residues, if false, scale is right
*/
- void drawWestScale(Graphics g, int startx, int endx, int ypos)
+ void drawVerticalScale(Graphics g, final int startx, final int endx,
+ final int ypos, final boolean left)
{
- FontMetrics fm = getFontMetrics(av.getFont());
- ypos += charHeight;
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
- if (av.hasHiddenColumns())
- {
- startx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(startx);
- endx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(endx);
- }
+ int yPos = ypos + charHeight;
+ int startX = startx;
+ int endX = endx;
- int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
+ HiddenColumns hiddenColumns = av.getAlignment().getHiddenColumns();
+ startX = hiddenColumns.adjustForHiddenColumns(startx);
+ endX = hiddenColumns.adjustForHiddenColumns(endx);
}
+ FontMetrics fm = getFontMetrics(av.getFont());
for (int i = 0; i < av.getAlignment().getHeight(); i++)
{
SequenceI seq = av.getAlignment().getSequenceAt(i);
- int index = startx;
- int value = -1;
- while (index < endx)
+ /*
+ * find sequence position of first non-gapped position -
+ * to the right if scale left, to the left if scale right
+ */
+ int index = left ? startX : endX;
+ int value = -1;
+ while (index >= startX && index <= endX)
{
- if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
+ if (!Comparison.isGap(seq.getCharAt(index)))
+ {
+ value = seq.findPosition(index);
+ break;
+ }
+ if (left)
{
index++;
-
- continue;
}
-
- value = av.getAlignment().getSequenceAt(i).findPosition(index);
-
- break;
- }
-
- if (value != -1)
- {
- int x = labelWidthWest - fm.stringWidth(String.valueOf(value))
- - charWidth / 2;
- g.drawString(value + "", x,
- (ypos + (i * charHeight)) - (charHeight / 5));
- }
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param g
- * DOCUMENT ME!
- * @param startx
- * DOCUMENT ME!
- * @param endx
- * DOCUMENT ME!
- * @param ypos
- * DOCUMENT ME!
- */
- void drawEastScale(Graphics g, int startx, int endx, int ypos)
- {
- ypos += charHeight;
-
- if (av.hasHiddenColumns())
- {
- endx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(endx);
- }
-
- SequenceI seq;
- // EAST SCALE
- for (int i = 0; i < av.getAlignment().getHeight(); i++)
- {
- seq = av.getAlignment().getSequenceAt(i);
- int index = endx;
- int value = -1;
-
- while (index > startx)
- {
- if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
+ else
{
index--;
-
- continue;
}
-
- value = seq.findPosition(index);
-
- break;
}
+ /*
+ * white fill the space for the scale
+ */
+ g.setColor(Color.white);
+ int y = (yPos + (i * charHeight)) - (charHeight / 5);
+ // fillRect origin is top left of rectangle
+ g.fillRect(0, y - charHeight, left ? labelWidthWest : labelWidthEast,
+ charHeight + 1);
+
if (value != -1)
{
- g.drawString(String.valueOf(value), 0,
- (ypos + (i * charHeight)) - (charHeight / 5));
+ /*
+ * draw scale value, right justified within its width less half a
+ * character width padding on the right
+ */
+ int labelSpace = left ? labelWidthWest : labelWidthEast;
+ labelSpace -= charWidth / 2; // leave space to the right
+ String valueAsString = String.valueOf(value);
+ int labelLength = fm.stringWidth(valueAsString);
+ int xOffset = labelSpace - labelLength;
+ g.setColor(Color.black);
+ g.drawString(valueAsString, xOffset, y);
}
}
}
-
/**
- * need to make this thread safe move alignment rendering in response to
- * slider adjustment
+ * Does a fast paint of an alignment in response to a scroll. Most of the
+ * visible region is simply copied and shifted, and then any newly visible
+ * columns or rows are drawn. The scroll may be horizontal or vertical, but
+ * not both at once. Scrolling may be the result of
+ * <ul>
+ * <li>dragging a scroll bar</li>
+ * <li>clicking in the scroll bar</li>
+ * <li>scrolling by trackpad, middle mouse button, or other device</li>
+ * <li>by moving the box in the Overview window</li>
+ * <li>programmatically to make a highlighted position visible</li>
+ * </ul>
*
* @param horizontal
- * shift along
+ * columns to shift right (positive) or left (negative)
* @param vertical
- * shift up or down in repaint
+ * rows to shift down (positive) or up (negative)
*/
public void fastPaint(int horizontal, int vertical)
{
}
fastpainting = true;
fastPaint = true;
- updateViewport();
- ViewportRanges ranges = av.getRanges();
- int startRes = ranges.getStartRes();
- int endRes = ranges.getEndRes();
- int startSeq = ranges.getStartSeq();
- int endSeq = ranges.getEndSeq();
- int transX = 0;
- int transY = 0;
+ try
+ {
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
+ ViewportRanges ranges = av.getRanges();
+ int startRes = ranges.getStartRes();
+ int endRes = ranges.getEndRes();
+ int startSeq = ranges.getStartSeq();
+ int endSeq = ranges.getEndSeq();
+ int transX = 0;
+ int transY = 0;
gg.copyArea(horizontal * charWidth, vertical * charHeight,
img.getWidth(), img.getHeight(), -horizontal * charWidth,
gg.translate(-transX, -transY);
repaint();
- fastpainting = false;
+ } finally
+ {
+ fastpainting = false;
+ }
}
@Override
public void paintComponent(Graphics g)
{
- super.paintComponent(g);
-
- updateViewport();
+ super.paintComponent(g);
+
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
ViewportRanges ranges = av.getRanges();
g.drawImage(lcimg, 0, 0, this);
}
}
-
+
/**
* Draw an alignment panel for printing
*
{
BufferedImage lcimg = null;
+ int charWidth = av.getCharWidth();
+ int charHeight = av.getCharHeight();
+
int width = getWidth();
int height = getHeight();
*/
public int getWrappedCanvasWidth(int canvasWidth)
{
- FontMetrics fm = getFontMetrics(av.getFont());
+ int charWidth = av.getCharWidth();
- labelWidthEast = 0;
- labelWidthWest = 0;
+ FontMetrics fm = getFontMetrics(av.getFont());
- if (av.getScaleRightWrapped())
+ int labelWidth = 0;
+
+ if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
{
- labelWidthEast = getLabelWidth(fm);
+ labelWidth = getLabelWidth(fm);
}
- if (av.getScaleLeftWrapped())
- {
- labelWidthWest = labelWidthEast > 0 ? labelWidthEast
- : getLabelWidth(fm);
- }
+ labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0;
+
+ labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0;
return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
}
/**
- * 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).
+ * Returns a pixel width sufficient to show the largest sequence coordinate
+ * (end position) in the alignment, calculated as the FontMetrics width of
+ * zeroes "0000000" limited to the number of decimal digits to be shown (3 for
+ * 1-10, 4 for 11-99 etc). One character width is added to this, to allow for
+ * half a character width space on either side.
*
* @param fm
* @return
maxWidth = Math.max(maxWidth, alignment.getSequenceAt(i).getEnd());
}
- int length = 2;
+ int length = 0;
for (int i = maxWidth; i > 0; i /= 10)
{
length++;
}
- return fm.stringWidth(ZEROS.substring(0, length));
+ return fm.stringWidth(ZEROS.substring(0, length)) + av.getCharWidth();
}
/**
- * DOCUMENT ME!
+ * Draws as many widths of a wrapped alignment as can fit in the visible
+ * window
*
* @param g
- * DOCUMENT ME!
* @param canvasWidth
- * DOCUMENT ME!
+ * available width in pixels
* @param canvasHeight
- * DOCUMENT ME!
- * @param startRes
- * DOCUMENT ME!
+ * available height in pixels
+ * @param startColumn
+ * the first column (0...) of the alignment to draw
*/
- private void drawWrappedPanel(Graphics g, int canvasWidth,
- int canvasHeight, int startRes)
+ public void drawWrappedPanel(Graphics g, int canvasWidth,
+ int canvasHeight, final int startColumn)
{
- updateViewport();
- AlignmentI al = av.getAlignment();
+ int wrappedWidthInResidues = calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
- int labelWidth = 0;
- if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
+ av.setWrappedWidth(wrappedWidthInResidues);
+
+ ViewportRanges ranges = av.getRanges();
+ ranges.setViewportStartAndWidth(startColumn, wrappedWidthInResidues);
+
+ /*
+ * draw one width at a time (including any scales or annotation shown),
+ * until we have run out of either alignment or vertical space available
+ */
+ int ypos = wrappedSpaceAboveAlignment;
+ int maxWidth = ranges.getVisibleAlignmentWidth();
+
+ int start = startColumn;
+ int currentWidth = 0;
+ while ((currentWidth < wrappedVisibleWidths) && (start < maxWidth))
{
- FontMetrics fm = getFontMetrics(av.getFont());
- labelWidth = getLabelWidth(fm);
+ int endColumn = Math
+ .min(maxWidth, start + wrappedWidthInResidues - 1);
+ drawWrappedWidth(g, ypos, start, endColumn, canvasHeight);
+ ypos += wrappedRepeatHeightPx;
+ start += wrappedWidthInResidues;
+ currentWidth++;
}
- labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0;
- labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0;
+ drawWrappedDecorators(g, startColumn);
+ }
- int hgap = charHeight;
- if (av.getScaleAboveWrapped())
+ /**
+ * Calculates and saves values needed when rendering a wrapped alignment.
+ * These depend on many factors, including
+ * <ul>
+ * <li>canvas width and height</li>
+ * <li>number of visible sequences, and height of annotations if shown</li>
+ * <li>font and character width</li>
+ * <li>whether scales are shown left, right or above the alignment</li>
+ * </ul>
+ *
+ * @param canvasWidth
+ * @param canvasHeight
+ * @return the number of residue columns in each width
+ */
+ protected int calculateWrappedGeometry(int canvasWidth, int canvasHeight)
+ {
+ int charHeight = av.getCharHeight();
+
+ /*
+ * vertical space in pixels between wrapped widths of alignment
+ * - one character height, or two if scale above is drawn
+ */
+ wrappedSpaceAboveAlignment = charHeight
+ * (av.getScaleAboveWrapped() ? 2 : 1);
+
+ /*
+ * height in pixels of the wrapped widths
+ */
+ wrappedRepeatHeightPx = wrappedSpaceAboveAlignment;
+ // add sequences
+ wrappedRepeatHeightPx += av.getRanges().getViewportHeight()
+ * charHeight;
+ // add annotations panel height if shown
+ wrappedRepeatHeightPx += getAnnotationHeight();
+
+ /*
+ * number of visible widths (the last one may be part height),
+ * ensuring a part height includes at least one sequence
+ */
+ ViewportRanges ranges = av.getRanges();
+ wrappedVisibleWidths = canvasHeight / wrappedRepeatHeightPx;
+ int remainder = canvasHeight % wrappedRepeatHeightPx;
+ if (remainder >= (wrappedSpaceAboveAlignment + charHeight))
{
- hgap += charHeight;
+ wrappedVisibleWidths++;
}
- int cWidth = (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
- int cHeight = av.getAlignment().getHeight() * charHeight;
+ /*
+ * compute width in residues; this also sets East and West label widths
+ */
+ int wrappedWidthInResidues = getWrappedCanvasWidth(canvasWidth);
- av.setWrappedWidth(cWidth);
+ /*
+ * limit visibleWidths to not exceed width of alignment
+ */
+ int xMax = ranges.getVisibleAlignmentWidth();
+ int startToEnd = xMax - ranges.getStartRes();
+ int maxWidths = startToEnd / wrappedWidthInResidues;
+ if (startToEnd % wrappedWidthInResidues > 0)
+ {
+ maxWidths++;
+ }
+ wrappedVisibleWidths = Math.min(wrappedVisibleWidths, maxWidths);
- av.getRanges().setViewportStartAndWidth(startRes, cWidth);
+ return wrappedWidthInResidues;
+ }
- int endx;
- int ypos = hgap;
- int maxwidth = av.getAlignment().getWidth();
+ /**
+ * Draws one width of a wrapped alignment, including sequences and
+ * annnotations, if shown, but not scales or hidden column markers
+ *
+ * @param g
+ * @param ypos
+ * @param startColumn
+ * @param endColumn
+ * @param canvasHeight
+ */
+ protected void drawWrappedWidth(Graphics g, int ypos, int startColumn,
+ int endColumn, int canvasHeight)
+ {
+ ViewportRanges ranges = av.getRanges();
+ int viewportWidth = ranges.getViewportWidth();
- if (av.hasHiddenColumns())
+ int endx = Math.min(startColumn + viewportWidth - 1, endColumn);
+
+ /*
+ * move right before drawing by the width of the scale left (if any)
+ * plus column offset from left margin (usually zero, but may be non-zero
+ * when fast painting is drawing just a few columns)
+ */
+ int charWidth = av.getCharWidth();
+ int xOffset = labelWidthWest
+ + ((startColumn - ranges.getStartRes()) % viewportWidth)
+ * charWidth;
+ g.translate(xOffset, 0);
+
+ // When printing we have an extra clipped region,
+ // the Printable page which we need to account for here
+ Shape clip = g.getClip();
+
+ if (clip == null)
{
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth);
+ g.setClip(0, 0, viewportWidth * charWidth, canvasHeight);
+ }
+ else
+ {
+ g.setClip(0, (int) clip.getBounds().getY(),
+ viewportWidth * charWidth, (int) clip.getBounds().getHeight());
}
- int annotationHeight = getAnnotationHeight();
+ /*
+ * white fill the region to be drawn (so incremental fast paint doesn't
+ * scribble over an existing image)
+ */
+ gg.setColor(Color.white);
+ gg.fillRect(0, ypos, (endx - startColumn + 1) * charWidth,
+ wrappedRepeatHeightPx);
- while ((ypos <= canvasHeight) && (startRes < maxwidth))
- {
- endx = startRes + cWidth - 1;
+ drawPanel(g, startColumn, endx, 0, av.getAlignment().getHeight() - 1,
+ ypos);
- if (endx > maxwidth)
+ int cHeight = av.getAlignment().getHeight() * av.getCharHeight();
+
+ if (av.isShowAnnotation())
+ {
+ g.translate(0, cHeight + ypos + 3);
+ if (annotations == null)
{
- endx = maxwidth;
+ annotations = new AnnotationPanel(av);
}
- g.setFont(av.getFont());
- g.setColor(Color.black);
+ annotations.renderer.drawComponent(annotations, av, g, -1,
+ startColumn, endx + 1);
+ g.translate(0, -cHeight - ypos - 3);
+ }
+ g.setClip(clip);
+ g.translate(-xOffset, 0);
+ }
+
+ /**
+ * Draws scales left, right and above (if shown), and any hidden column
+ * markers, on all widths of the wrapped alignment
+ *
+ * @param g
+ * @param startColumn
+ */
+ protected void drawWrappedDecorators(Graphics g, final int startColumn)
+ {
+ int charWidth = av.getCharWidth();
+
+ g.setFont(av.getFont());
+ g.setColor(Color.black);
+
+ int ypos = wrappedSpaceAboveAlignment;
+ ViewportRanges ranges = av.getRanges();
+ int viewportWidth = ranges.getViewportWidth();
+ int maxWidth = ranges.getVisibleAlignmentWidth();
+ int widthsDrawn = 0;
+ int startCol = startColumn;
+
+ while (widthsDrawn < wrappedVisibleWidths)
+ {
+ int endColumn = Math.min(maxWidth, startCol + viewportWidth - 1);
if (av.getScaleLeftWrapped())
{
- drawWestScale(g, startRes, endx, ypos);
+ drawVerticalScale(g, startCol, endColumn - 1, ypos, true);
}
if (av.getScaleRightWrapped())
{
- g.translate(canvasWidth - labelWidthEast, 0);
- drawEastScale(g, startRes, endx, ypos);
- g.translate(-(canvasWidth - labelWidthEast), 0);
+ int x = labelWidthWest + viewportWidth * charWidth;
+ g.translate(x, 0);
+ drawVerticalScale(g, startCol, endColumn, ypos, false);
+ g.translate(-x, 0);
}
+ /*
+ * white fill region of scale above and hidden column markers
+ * (to support incremental fast paint of image)
+ */
+ g.translate(labelWidthWest, 0);
+ g.setColor(Color.white);
+ g.fillRect(0, ypos - wrappedSpaceAboveAlignment, viewportWidth
+ * charWidth + labelWidthWest, wrappedSpaceAboveAlignment);
+ g.setColor(Color.black);
+ g.translate(-labelWidthWest, 0);
+
g.translate(labelWidthWest, 0);
if (av.getScaleAboveWrapped())
{
- drawNorthScale(g, startRes, endx, ypos);
+ drawNorthScale(g, startCol, endColumn, ypos);
}
if (av.hasHiddenColumns() && av.getShowHiddenMarkers())
{
- g.setColor(Color.blue);
- int res;
- HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-
- Iterator<Integer> it = hidden.getBoundedStartIterator(startRes,
- endx + 1);
- while (it.hasNext())
- {
- res = it.next() - startRes;
- gg.fillPolygon(
- new int[]
- { res * charWidth - charHeight / 4,
- res * charWidth + charHeight / 4, res * charWidth },
- new int[]
- { ypos - (charHeight / 2), ypos - (charHeight / 2),
- ypos - (charHeight / 2) + 8 }, 3);
- }
+ drawHiddenColumnMarkers(g, ypos, startCol, endColumn);
}
- // When printing we have an extra clipped region,
- // the Printable page which we need to account for here
- Shape clip = g.getClip();
+ g.translate(-labelWidthWest, 0);
- if (clip == null)
- {
- g.setClip(0, 0, cWidth * charWidth, canvasHeight);
- }
- else
- {
- g.setClip(0, (int) clip.getBounds().getY(), cWidth * charWidth,
- (int) clip.getBounds().getHeight());
- }
+ ypos += wrappedRepeatHeightPx;
+ startCol += viewportWidth;
+ widthsDrawn++;
+ }
+ }
- drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
+ /**
+ * Draws markers (triangles) above hidden column positions between startColumn
+ * and endColumn.
+ *
+ * @param g
+ * @param ypos
+ * @param startColumn
+ * @param endColumn
+ */
+ protected void drawHiddenColumnMarkers(Graphics g, int ypos,
+ int startColumn, int endColumn)
+ {
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
- if (av.isShowAnnotation())
- {
- g.translate(0, cHeight + ypos + 3);
- if (annotations == null)
- {
- annotations = new AnnotationPanel(av);
- }
+ g.setColor(Color.blue);
++ int res;
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- List<Integer> positions = hidden.findHiddenRegionPositions();
- for (int pos : positions)
+
- annotations.renderer.drawComponent(annotations, av, g, -1, startRes,
- endx + 1);
- g.translate(0, -cHeight - ypos - 3);
- }
- g.setClip(clip);
- g.translate(-labelWidthWest, 0);
++ Iterator<Integer> it = hidden.getBoundedStartIterator(startColumn,
++ endColumn);
++ while (it.hasNext())
+ {
- int res = pos - startColumn;
++ res = it.next() - startColumn;
- ypos += cHeight + annotationHeight + hgap;
+ if (res < 0 || res > endColumn - startColumn + 1)
+ {
+ continue;
+ }
- startRes += cWidth;
+ /*
+ * draw a downward-pointing triangle at the hidden columns location
+ * (before the following visible column)
+ */
+ int xMiddle = res * charWidth;
+ int[] xPoints = new int[] { xMiddle - charHeight / 4,
+ xMiddle + charHeight / 4, xMiddle };
+ int yTop = ypos - (charHeight / 2);
+ int[] yPoints = new int[] { yTop, yTop, yTop + 8 };
+ g.fillPolygon(xPoints, yPoints, 3);
}
}
int canvasWidth,
int canvasHeight, int startRes)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
// height gap above each panel
int hgap = charHeight;
if (av.getScaleAboveWrapped())
* marker.
*
* @param g1
- * Graphics object to draw with
+ * the graphics context, positioned at the first residue to be drawn
* @param startRes
- * offset of the first column in the visible region (0..)
+ * offset of the first column to draw (0..)
* @param endRes
- * offset of the last column in the visible region (0..)
+ * offset of the last column to draw (0..)
* @param startSeq
- * offset of the first sequence in the visible region (0..)
+ * offset of the first sequence to draw (0..)
* @param endSeq
- * offset of the last sequence in the visible region (0..)
+ * offset of the last sequence to draw (0..)
* @param yOffset
* vertical offset at which to draw (for wrapped alignments)
*/
public void drawPanel(Graphics g1, final int startRes, final int endRes,
final int startSeq, final int endSeq, final int yOffset)
{
- updateViewport();
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
if (!av.hasHiddenColumns())
{
draw(g1, startRes, endRes, startSeq, endSeq, yOffset);
else
{
int screenY = 0;
- final int screenYMax = endRes - startRes;
- int blockStart = startRes;
- int blockEnd = endRes;
+ int blockStart;
+ int blockEnd;
- for (int[] region : av.getAlignment().getHiddenColumns()
- .getHiddenColumnsCopy())
- {
- int hideStart = region[0];
- int hideEnd = region[1];
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ VisibleBlocksVisBoundsIterator regions = (VisibleBlocksVisBoundsIterator) hidden
+ .getVisibleBlocksIterator(startRes, endRes, true);
- if (hideStart <= blockStart)
- {
- blockStart += (hideEnd - hideStart) + 1;
- continue;
- }
+ while (regions.hasNext())
+ {
+ int[] region = regions.next();
+ blockEnd = region[1];
+ blockStart = region[0];
/*
* draw up to just before the next hidden region, or the end of
* the visible region, whichever comes first
*/
- blockEnd = Math.min(hideStart - 1, blockStart + screenYMax
- - screenY);
-
g1.translate(screenY * charWidth, 0);
draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
* draw the downline of the hidden column marker (ScalePanel draws the
* triangle on top) if we reached it
*/
- if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1)
+ if (av.getShowHiddenMarkers()
+ && (regions.hasNext() || regions.endsAtHidden()))
{
g1.setColor(Color.blue);
g1.translate(-screenY * charWidth, 0);
screenY += blockEnd - blockStart + 1;
- blockStart = hideEnd + 1;
-
- if (screenY > screenYMax)
- {
- // already rendered last block
- return;
- }
- }
-
- if (screenY <= screenYMax)
- {
- // remaining visible region to render
- blockEnd = blockStart + screenYMax - screenY;
- g1.translate(screenY * charWidth, 0);
- draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
-
- g1.translate(-screenY * charWidth, 0);
}
}
private void draw(Graphics g, int startRes, int endRes, int startSeq,
int endSeq, int offset)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
g.setFont(av.getFont());
seqRdr.prepare(g, av.isRenderGaps());
private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
int startRes, int endRes, int startSeq, int endSeq, int offset)
{
+ int charWidth = av.getCharWidth();
+
if (!av.hasHiddenColumns())
{
drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq,
{
// package into blocks of visible columns
int screenY = 0;
- int blockStart = startRes;
- int blockEnd = endRes;
+ int blockStart;
+ int blockEnd;
- for (int[] region : av.getAlignment().getHiddenColumns()
- .getHiddenColumnsCopy())
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ VisibleBlocksVisBoundsIterator regions = (VisibleBlocksVisBoundsIterator) hidden
+ .getVisibleBlocksIterator(startRes, endRes, true);
+ while (regions.hasNext())
{
- int hideStart = region[0];
- int hideEnd = region[1];
-
- if (hideStart <= blockStart)
- {
- blockStart += (hideEnd - hideStart) + 1;
- continue;
- }
-
- blockEnd = hideStart - 1;
+ int[] region = regions.next();
+ blockEnd = region[1];
+ blockStart = region[0];
g.translate(screenY * charWidth, 0);
drawPartialGroupOutline(g, group,
g.translate(-screenY * charWidth, 0);
screenY += blockEnd - blockStart + 1;
- blockStart = hideEnd + 1;
-
- if (screenY > (endRes - startRes))
- {
- // already rendered last block
- break;
- }
- }
-
- if (screenY <= (endRes - startRes))
- {
- // remaining visible region to render
- blockEnd = blockStart + (endRes - startRes) - screenY;
- g.translate(screenY * charWidth, 0);
- drawPartialGroupOutline(g, group,
- blockStart, blockEnd, startSeq, endSeq, offset);
-
- g.translate(-screenY * charWidth, 0);
}
}
}
int startRes, int endRes, int startSeq, int endSeq,
int verticalOffset)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
int visWidth = (endRes - startRes + 1) * charWidth;
int oldY = -1;
return false;
}
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
{
fastPaint = true;
repaint();
+ return;
}
- else if (av.getWrapAlignment())
+
+ int scrollX = 0;
+ if (eventName.equals(ViewportRanges.STARTRES))
{
- if (eventName.equals(ViewportRanges.STARTRES))
+ // Make sure we're not trying to draw a panel
+ // larger than the visible window
+ ViewportRanges vpRanges = av.getRanges();
+ scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+ int range = vpRanges.getViewportWidth();
+ if (scrollX > range)
{
- repaint();
+ scrollX = range;
+ }
+ else if (scrollX < -range)
+ {
+ scrollX = -range;
}
}
- else
+
+ // 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.
+
+ // scroll - startres and endres both change
+ if (eventName.equals(ViewportRanges.STARTRES))
{
- int scrollX = 0;
- if (eventName.equals(ViewportRanges.STARTRES))
+ if (av.getWrapAlignment())
{
- // Make sure we're not trying to draw a panel
- // larger than the visible window
- ViewportRanges vpRanges = av.getRanges();
- scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
- int range = vpRanges.getEndRes() - vpRanges.getStartRes();
- if (scrollX > range)
- {
- scrollX = range;
- }
- else if (scrollX < -range)
- {
- scrollX = -range;
- }
+ fastPaintWrapped(scrollX);
}
-
- // 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))
+ else
{
- // scroll - startres and endres both change
fastPaint(scrollX, 0);
}
- else if (eventName.equals(ViewportRanges.STARTSEQ))
+ }
+ else if (eventName.equals(ViewportRanges.STARTSEQ))
+ {
+ // scroll
+ fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+ }
+ }
+
+ /**
+ * Does a minimal update of the image for a scroll movement. This method
+ * handles scroll movements of up to one width of the wrapped alignment (one
+ * click in the vertical scrollbar). Larger movements (for example after a
+ * scroll to highlight a mapped position) trigger a full redraw instead.
+ *
+ * @param scrollX
+ * number of positions scrolled (right if positive, left if negative)
+ */
+ protected void fastPaintWrapped(int scrollX)
+ {
+ ViewportRanges ranges = av.getRanges();
+
+ if (Math.abs(scrollX) > ranges.getViewportWidth())
+ {
+ /*
+ * shift of more than one view width is
+ * overcomplicated to handle in this method
+ */
+ fastPaint = false;
+ repaint();
+ return;
+ }
+
+ if (fastpainting || gg == null)
+ {
+ return;
+ }
+
+ fastPaint = true;
+ fastpainting = true;
+
+ try
+ {
+ calculateWrappedGeometry(getWidth(), getHeight());
+
+ /*
+ * relocate the regions of the alignment that are still visible
+ */
+ shiftWrappedAlignment(-scrollX);
+
+ /*
+ * add new columns (sequence, annotation)
+ * - at top left if scrollX < 0
+ * - at right of last two widths if scrollX > 0
+ */
+ if (scrollX < 0)
+ {
+ int startRes = ranges.getStartRes();
+ drawWrappedWidth(gg, wrappedSpaceAboveAlignment, startRes, startRes
+ - scrollX - 1, getHeight());
+ }
+ else
{
- // scroll
- fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+ fastPaintWrappedAddRight(scrollX);
}
+
+ /*
+ * draw all scales (if shown) and hidden column markers
+ */
+ drawWrappedDecorators(gg, ranges.getStartRes());
+
+ repaint();
+ } finally
+ {
+ fastpainting = false;
+ }
+ }
+
+ /**
+ * Draws the specified number of columns at the 'end' (bottom right) of a
+ * wrapped alignment view, including sequences and annotations if shown, but
+ * not scales. Also draws the same number of columns at the right hand end of
+ * the second last width shown, if the last width is not full height (so
+ * cannot simply be copied from the graphics image).
+ *
+ * @param columns
+ */
+ protected void fastPaintWrappedAddRight(int columns)
+ {
+ if (columns == 0)
+ {
+ return;
+ }
+
+ ViewportRanges ranges = av.getRanges();
+ int viewportWidth = ranges.getViewportWidth();
+ int charWidth = av.getCharWidth();
+
+ /**
+ * draw full height alignment in the second last row, last columns, if the
+ * last row was not full height
+ */
+ int visibleWidths = wrappedVisibleWidths;
+ int canvasHeight = getHeight();
+ boolean lastWidthPartHeight = (wrappedVisibleWidths * wrappedRepeatHeightPx) > canvasHeight;
+
+ if (lastWidthPartHeight)
+ {
+ int widthsAbove = Math.max(0, visibleWidths - 2);
+ int ypos = wrappedRepeatHeightPx * widthsAbove
+ + wrappedSpaceAboveAlignment;
+ int endRes = ranges.getEndRes();
+ endRes += widthsAbove * viewportWidth;
+ int startRes = endRes - columns;
+ int xOffset = ((startRes - ranges.getStartRes()) % viewportWidth)
+ * charWidth;
+
+ /*
+ * white fill first to erase annotations
+ */
+ gg.translate(xOffset, 0);
+ gg.setColor(Color.white);
+ gg.fillRect(labelWidthWest, ypos,
+ (endRes - startRes + 1) * charWidth, wrappedRepeatHeightPx);
+ gg.translate(-xOffset, 0);
+
+ drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+ }
+
+ /*
+ * draw newly visible columns in last wrapped width (none if we
+ * have reached the end of the alignment)
+ * y-offset for drawing last width is height of widths above,
+ * plus one gap row
+ */
+ int widthsAbove = visibleWidths - 1;
+ int ypos = wrappedRepeatHeightPx * widthsAbove
+ + wrappedSpaceAboveAlignment;
+ int endRes = ranges.getEndRes();
+ endRes += widthsAbove * viewportWidth;
+ int startRes = endRes - columns + 1;
+
+ /*
+ * white fill first to erase annotations
+ */
+ int xOffset = ((startRes - ranges.getStartRes()) % viewportWidth)
+ * charWidth;
+ gg.translate(xOffset, 0);
+ gg.setColor(Color.white);
+ int width = viewportWidth * charWidth - xOffset;
+ gg.fillRect(labelWidthWest, ypos, width, wrappedRepeatHeightPx);
+ gg.translate(-xOffset, 0);
+
+ gg.setFont(av.getFont());
+ gg.setColor(Color.black);
+
+ if (startRes < ranges.getVisibleAlignmentWidth())
+ {
+ drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+ }
+
+ /*
+ * and finally, white fill any space below the visible alignment
+ */
+ int heightBelow = canvasHeight - visibleWidths * wrappedRepeatHeightPx;
+ if (heightBelow > 0)
+ {
+ gg.setColor(Color.white);
+ gg.fillRect(0, canvasHeight - heightBelow, getWidth(), heightBelow);
}
}
/**
+ * Shifts the visible alignment by the specified number of columns - left if
+ * negative, right if positive. Copies and moves sequences and annotations (if
+ * shown). Scales, hidden column markers and any newly visible columns must be
+ * drawn separately.
+ *
+ * @param positions
+ */
+ protected void shiftWrappedAlignment(int positions)
+ {
+ if (positions == 0)
+ {
+ return;
+ }
+ int charWidth = av.getCharWidth();
+
+ int canvasHeight = getHeight();
+ ViewportRanges ranges = av.getRanges();
+ int viewportWidth = ranges.getViewportWidth();
+ int widthToCopy = (ranges.getViewportWidth() - Math.abs(positions))
+ * charWidth;
+ int heightToCopy = wrappedRepeatHeightPx - wrappedSpaceAboveAlignment;
+ int xMax = ranges.getVisibleAlignmentWidth();
+
+ if (positions > 0)
+ {
+ /*
+ * shift right (after scroll left)
+ * for each wrapped width (starting with the last), copy (width-positions)
+ * columns from the left margin to the right margin, and copy positions
+ * columns from the right margin of the row above (if any) to the
+ * left margin of the current row
+ */
+
+ /*
+ * get y-offset of last wrapped width, first row of sequences
+ */
+ int y = canvasHeight / wrappedRepeatHeightPx * wrappedRepeatHeightPx;
+ y += wrappedSpaceAboveAlignment;
+ int copyFromLeftStart = labelWidthWest;
+ int copyFromRightStart = copyFromLeftStart + widthToCopy;
+
+ while (y >= 0)
+ {
+ gg.copyArea(copyFromLeftStart, y, widthToCopy, heightToCopy,
+ positions * charWidth, 0);
+ if (y > 0)
+ {
+ gg.copyArea(copyFromRightStart, y - wrappedRepeatHeightPx,
+ positions * charWidth, heightToCopy, -widthToCopy,
+ wrappedRepeatHeightPx);
+ }
+
+ y -= wrappedRepeatHeightPx;
+ }
+ }
+ else
+ {
+ /*
+ * shift left (after scroll right)
+ * for each wrapped width (starting with the first), copy (width-positions)
+ * columns from the right margin to the left margin, and copy positions
+ * columns from the left margin of the row below (if any) to the
+ * right margin of the current row
+ */
+ int xpos = av.getRanges().getStartRes();
+ int y = wrappedSpaceAboveAlignment;
+ int copyFromRightStart = labelWidthWest - positions * charWidth;
+
+ while (y < canvasHeight)
+ {
+ gg.copyArea(copyFromRightStart, y, widthToCopy, heightToCopy,
+ positions * charWidth, 0);
+ if (y + wrappedRepeatHeightPx < canvasHeight - wrappedRepeatHeightPx
+ && (xpos + viewportWidth <= xMax))
+ {
+ gg.copyArea(labelWidthWest, y + wrappedRepeatHeightPx, -positions
+ * charWidth, heightToCopy, widthToCopy,
+ -wrappedRepeatHeightPx);
+ }
+
+ y += wrappedRepeatHeightPx;
+ xpos += viewportWidth;
+ }
+ }
+ }
+
+
+ /**
* 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
{
return false;
}
-
+ int charHeight = av.getCharHeight();
+
boolean matchFound = false;
+ calculateWrappedGeometry(getWidth(), getHeight());
int wrappedWidth = av.getWrappedWidth();
- int wrappedHeight = getRepeatHeightWrapped();
+ int wrappedHeight = wrappedRepeatHeightPx;
ViewportRanges ranges = av.getRanges();
int canvasHeight = getHeight();
}
/**
- * 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
+ * Answers the width in pixels of the left scale labels (0 if not shown)
*
* @return
*/
- protected int getRepeatHeightWrapped()
+ int getLabelWidthWest()
{
- // 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;
+ return labelWidthWest;
}
}
*/
public class ScaleRenderer
{
+ /**
+ * Represents one major or minor scale mark
+ */
public final class ScaleMark
{
+ /**
+ * true for a major scale mark, false for minor
+ */
public final boolean major;
+ /**
+ * visible column position (0..) e.g. 19
+ */
public final int column;
+ /**
+ * text (if any) to show e.g. "20"
+ */
public final String text;
ScaleMark(boolean isMajor, int col, String txt)
column = col;
text = txt;
}
}
/**
- * Calculates position markers on the alignment ruler
+ * calculate positions markers on the alignment ruler
*
* @param av
* @param startx
- * left-most column in visible view (0..)
+ * left-most column in visible view
* @param endx
- * - right-most column in visible view (0..)
- * @return
+ * - right-most column in visible view
+ * @return List of ScaleMark holding boolean: true/false for major/minor mark,
+ * marker position in alignment column coords, a String to be rendered
+ * at the position (or null)
*/
public List<ScaleMark> calculateMarks(AlignViewportI av, int startx,
int endx)
int scalestartx = (startx / 10) * 10;
SequenceI refSeq = av.getAlignment().getSeqrep();
- int refSp = 0, refStartI = 0, refEndI = -1;
+ int refSp = 0;
+ int refStartI = 0;
+ int refEndI = -1;
if (refSeq != null)
{
- // find bounds and set origin appopriately
+ // find bounds and set origin appropriately
// locate first visible position for this sequence
- int[] refbounds = av.getAlignment().getHiddenColumns()
- .locateVisibleBoundsOfSequence(refSeq);
+ refSp = av.getAlignment().getHiddenColumns()
+ .locateVisibleStartOfSequence(refSeq);
+
+ refStartI = refSeq.findIndex(refSeq.getStart()) - 1;
+
+ int seqlength = refSeq.getLength();
+ // get sequence position past the end of the sequence
+ int pastEndPos = refSeq.findPosition(seqlength + 1);
+ refEndI = refSeq.findIndex(pastEndPos - 1) - 1;
- refSp = refbounds[0];
- refStartI = refbounds[4];
- refEndI = refbounds[5];
scalestartx = refSp + ((scalestartx - refSp) / 10) * 10;
}
{
scalestartx += 5;
}
- List<ScaleMark> marks = new ArrayList<ScaleMark>();
+ List<ScaleMark> marks = new ArrayList<>();
+ String string;
+ int refN, iadj;
// todo: add a 'reference origin column' to set column number relative to
- for (int i = scalestartx; i <= endx; i += 5)
+ for (int i = scalestartx; i < endx; i += 5)
{
if (((i - refSp) % 10) == 0)
{
- String text;
if (refSeq == null)
{
- int iadj = av.getAlignment().getHiddenColumns()
+ iadj = av.getAlignment().getHiddenColumns()
.adjustForHiddenColumns(i - 1) + 1;
- text = String.valueOf(iadj);
+ string = String.valueOf(iadj);
}
else
{
- int iadj = av.getAlignment().getHiddenColumns()
+ iadj = av.getAlignment().getHiddenColumns()
.adjustForHiddenColumns(i - 1);
- int refN = refSeq.findPosition(iadj);
+ refN = refSeq.findPosition(iadj);
// TODO show bounds if position is a gap
// - ie L--R -> "1L|2R" for
// marker
if (iadj < refStartI)
{
- text = String.valueOf(iadj - refStartI);
+ string = String.valueOf(iadj - refStartI);
}
else if (iadj > refEndI)
{
- text = "+" + String.valueOf(iadj - refEndI);
+ string = "+" + String.valueOf(iadj - refEndI);
}
else
{
- text = String.valueOf(refN) + refSeq.getCharAt(iadj);
+ string = String.valueOf(refN) + refSeq.getCharAt(iadj);
}
}
- marks.add(new ScaleMark(true, i - startx - 1, text));
+ marks.add(new ScaleMark(true, i - startx - 1, string));
}
else
{
toSequences, fromGapChar);
}
- for (int[] hidden : hiddencols.getHiddenColumnsCopy())
+ Iterator<int[]> regions = hiddencols.iterator();
+ while (regions.hasNext())
{
- mapHiddenColumns(hidden, codonFrames, newHidden, fromSequences,
+ mapHiddenColumns(regions.next(), codonFrames, newHidden,
+ fromSequences,
toSequences, fromGapChar);
}
return; // mappedColumns;
}
return copy;
}
+
+ /**
+ * Removes the specified number of positions from the given ranges. Provided
+ * to allow a stop codon to be stripped from a CDS sequence so that it matches
+ * the peptide translation length.
+ *
+ * @param positions
+ * @param ranges
+ * a list of (single) [start, end] ranges
+ * @return
+ */
+ public static void removeEndPositions(int positions,
+ List<int[]> ranges)
+ {
+ int toRemove = positions;
+ Iterator<int[]> it = new ReverseListIterator<>(ranges);
+ while (toRemove > 0)
+ {
+ int[] endRange = it.next();
+ if (endRange.length != 2)
+ {
+ /*
+ * not coded for [start1, end1, start2, end2, ...]
+ */
+ System.err
+ .println("MappingUtils.removeEndPositions doesn't handle multiple ranges");
+ return;
+ }
+
+ int length = endRange[1] - endRange[0] + 1;
+ if (length <= 0)
+ {
+ /*
+ * not coded for a reverse strand range (end < start)
+ */
+ System.err
+ .println("MappingUtils.removeEndPositions doesn't handle reverse strand");
+ return;
+ }
+ if (length > toRemove)
+ {
+ endRange[1] -= toRemove;
+ toRemove = 0;
+ }
+ else
+ {
+ toRemove -= length;
+ it.remove();
+ }
+ }
+ }
}
import java.util.List;
import java.util.Vector;
-import junit.extensions.PA;
-
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import junit.extensions.PA;
+
public class SequenceTest
{
Assert.assertEquals(pdbe1a,
sq.getDatasetSequence().getPDBEntry("1PDB"),
"PDB Entry '1PDB' not found on dataset sequence via getPDBEntry.");
- ArrayList<Annotation> annotsList = new ArrayList<Annotation>();
+ ArrayList<Annotation> annotsList = new ArrayList<>();
System.out.println(">>>>>> " + sq.getSequenceAsString().length());
annotsList.add(new Annotation("A", "A", 'X', 0.1f));
annotsList.add(new Annotation("A", "A", 'X', 0.1f));
}
@Test(groups = { "Functional" })
+ public void testGapBitset()
+ {
+ SequenceI sq = new Sequence("test/8-13", "-ABC---DE-F--");
+ BitSet bs = sq.gapBitset();
+ BitSet expected = new BitSet();
+ expected.set(0);
+ expected.set(4, 7);
+ expected.set(9);
+ expected.set(11, 13);
+
+ assertTrue(bs.equals(expected));
+
+ }
++
+ public void testFindFeatures_largeEndPos()
+ {
+ /*
+ * imitate a PDB sequence where end is larger than end position
+ */
+ SequenceI sq = new Sequence("test", "-ABC--DEF--", 1, 20);
+ sq.createDatasetSequence();
+
+ assertTrue(sq.findFeatures(1, 9).isEmpty());
+ // should be no array bounds exception - JAL-2772
+ assertTrue(sq.findFeatures(1, 15).isEmpty());
+
+ // add feature on BCD
+ SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 2, 4, 2f,
+ null);
+ sq.addSequenceFeature(sfBCD);
+
+ // no features in columns 1-2 (-A)
+ List<SequenceFeature> found = sq.findFeatures(1, 2);
+ assertTrue(found.isEmpty());
+
+ // columns 1-6 (-ABC--) includes BCD
+ found = sq.findFeatures(1, 6);
+ assertEquals(1, found.size());
+ assertTrue(found.contains(sfBCD));
+
+ // columns 10-11 (--) should find nothing
+ found = sq.findFeatures(10, 11);
+ assertEquals(0, found.size());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testSetName()
+ {
+ SequenceI sq = new Sequence("test", "-ABC---DE-F--");
+ assertEquals("test", sq.getName());
+ assertEquals(1, sq.getStart());
+ assertEquals(6, sq.getEnd());
+
+ sq.setName("testing");
+ assertEquals("testing", sq.getName());
+
+ sq.setName("test/8-10");
+ assertEquals("test", sq.getName());
+ assertEquals(8, sq.getStart());
+ assertEquals(13, sq.getEnd()); // note end is recomputed
+
+ sq.setName("testing/7-99");
+ assertEquals("testing", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd()); // end may be beyond physical end
+
+ sq.setName("/2-3");
+ assertEquals("", sq.getName());
+ assertEquals(2, sq.getStart());
+ assertEquals(7, sq.getEnd());
+
+ sq.setName("test/"); // invalid
+ assertEquals("test/", sq.getName());
+ assertEquals(2, sq.getStart());
+ assertEquals(7, sq.getEnd());
+
+ sq.setName("test/6-13/7-99");
+ assertEquals("test/6-13", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/0-5"); // 0 is invalid - ignored
+ assertEquals("test/0-5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/a-5"); // a is invalid - ignored
+ assertEquals("test/a-5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/6-5"); // start > end is invalid - ignored
+ assertEquals("test/6-5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/5"); // invalid - ignored
+ assertEquals("test/5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/-5"); // invalid - ignored
+ assertEquals("test/-5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/5-"); // invalid - ignored
+ assertEquals("test/5-", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/5-6-7"); // invalid - ignored
+ assertEquals("test/5-6-7", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName(null); // invalid, gets converted to space
+ assertEquals("", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testCheckValidRange()
+ {
+ Sequence sq = new Sequence("test/7-12", "-ABC---DE-F--");
+ assertEquals(7, sq.getStart());
+ assertEquals(12, sq.getEnd());
+
+ /*
+ * checkValidRange ensures end is at least the last residue position
+ */
+ PA.setValue(sq, "end", 2);
+ sq.checkValidRange();
+ assertEquals(12, sq.getEnd());
+
+ /*
+ * end may be beyond the last residue position
+ */
+ PA.setValue(sq, "end", 22);
+ sq.checkValidRange();
+ assertEquals(22, sq.getEnd());
+ }
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
import org.testng.annotations.BeforeClass;
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
assertEquals("[]", dnaSelection.getSelected().toString());
- List<int[]> hidden = dnaHidden.getHiddenColumnsCopy();
- assertEquals(1, hidden.size());
- assertEquals("[0, 4]", Arrays.toString(hidden.get(0)));
+ Iterator<int[]> regions = dnaHidden.iterator();
+ assertEquals(1, dnaHidden.getNumberOfRegions());
+ assertEquals("[0, 4]", Arrays.toString(regions.next()));
/*
* Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
proteinSelection.hideSelectedColumns(1, hiddenCols);
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
- hidden = dnaHidden.getHiddenColumnsCopy();
- assertEquals(1, hidden.size());
- assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
+ regions = dnaHidden.iterator();
+ assertEquals(1, dnaHidden.getNumberOfRegions());
+ assertEquals("[0, 3]", Arrays.toString(regions.next()));
/*
* Column 2 in protein picks up gaps only - no mapping
proteinSelection.hideSelectedColumns(2, hiddenCols);
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
- assertTrue(dnaHidden.getHiddenColumnsCopy().isEmpty());
+ assertEquals(0, dnaHidden.getNumberOfRegions());
/*
* 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.getHiddenColumnsCopy();
- assertEquals(1, hidden.size());
- assertEquals("[5, 10]", Arrays.toString(hidden.get(0)));
+ regions = dnaHidden.iterator();
+ assertEquals(1, dnaHidden.getNumberOfRegions());
+ assertEquals("[5, 10]", Arrays.toString(regions.next()));
/*
* Combine hiding columns 1 and 3 to get discontiguous hidden columns
proteinSelection.hideSelectedColumns(3, hiddenCols);
MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
proteinView, dnaView, dnaSelection, dnaHidden);
- hidden = dnaHidden.getHiddenColumnsCopy();
- assertEquals(2, hidden.size());
- assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
- assertEquals("[5, 10]", Arrays.toString(hidden.get(1)));
+ regions = dnaHidden.iterator();
+ assertEquals(2, dnaHidden.getNumberOfRegions());
+ assertEquals("[0, 3]", Arrays.toString(regions.next()));
+ assertEquals("[5, 10]", Arrays.toString(regions.next()));
}
@Test(groups = { "Functional" })
assertEquals("[12, 11, 8, 4]", Arrays.toString(ranges));
}
+ @Test(groups = "Functional")
+ public void testRemoveEndPositions()
+ {
+ List<int[]> ranges = new ArrayList<>();
+
+ /*
+ * case 1: truncate last range
+ */
+ ranges.add(new int[] { 1, 10 });
+ ranges.add(new int[] { 20, 30 });
+ MappingUtils.removeEndPositions(5, ranges);
+ assertEquals(2, ranges.size());
+ assertEquals(25, ranges.get(1)[1]);
+
+ /*
+ * case 2: remove last range
+ */
+ ranges.clear();
+ ranges.add(new int[] { 1, 10 });
+ ranges.add(new int[] { 20, 22 });
+ MappingUtils.removeEndPositions(3, ranges);
+ assertEquals(1, ranges.size());
+ assertEquals(10, ranges.get(0)[1]);
+
+ /*
+ * case 3: truncate penultimate range
+ */
+ ranges.clear();
+ ranges.add(new int[] { 1, 10 });
+ ranges.add(new int[] { 20, 21 });
+ MappingUtils.removeEndPositions(3, ranges);
+ assertEquals(1, ranges.size());
+ assertEquals(9, ranges.get(0)[1]);
+
+ /*
+ * case 4: remove last two ranges
+ */
+ ranges.clear();
+ ranges.add(new int[] { 1, 10 });
+ ranges.add(new int[] { 20, 20 });
+ ranges.add(new int[] { 30, 30 });
+ MappingUtils.removeEndPositions(3, ranges);
+ assertEquals(1, ranges.size());
+ assertEquals(9, ranges.get(0)[1]);
+ }
}