*/
package jalview.viewmodel;
-import java.awt.Color;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.analysis.Conservation;
import jalview.api.AlignCalcManagerI;
import jalview.datamodel.Annotation;
import jalview.datamodel.CigarArray;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenSequences;
+import jalview.datamodel.SearchResults;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceGroup;
import jalview.structure.CommandListener;
import jalview.structure.StructureSelectionManager;
import jalview.structure.VamsasSource;
+import jalview.util.Comparison;
+import jalview.util.MappingUtils;
import jalview.viewmodel.styles.ViewStyle;
import jalview.workers.AlignCalcManager;
import jalview.workers.ComplementConsensusThread;
import jalview.workers.ConsensusThread;
import jalview.workers.StrucConsensusThread;
+import java.awt.Color;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* base class holding visualization and analysis attributes and common logic for
* an active alignment view displayed in the GUI
*
*/
public abstract class AlignmentViewport implements AlignViewportI,
- ViewStyleI, CommandListener, VamsasSource
+ CommandListener, VamsasSource
{
protected ViewStyleI viewStyle = new ViewStyle();
}
/**
- * @param selected
- * @see jalview.api.ViewStyleI#setShowSeqFeaturesHeight(boolean)
- */
- public void setShowSeqFeaturesHeight(boolean selected)
- {
- viewStyle.setShowSeqFeaturesHeight(selected);
- }
-
- /**
* alignment displayed in the viewport. Please use get/setter
*/
protected AlignmentI alignment;
// hasHiddenColumns = colSel.hasHiddenColumns();
}
- protected boolean hasHiddenRows = false;
-
@Override
public boolean hasHiddenRows()
{
- return hasHiddenRows;
+ return alignment.getHiddenSequences().getSize() > 0;
}
+
protected SequenceGroup selectionGroup;
public void setSequenceSetId(String newid)
protected boolean showAutocalculatedAbove;
/**
+ * when set, view will scroll to show the highlighted position
+ */
+ private boolean followHighlight = true;
+
+ // TODO private with getters and setters?
+ public int startRes;
+
+ public int endRes;
+
+ public int startSeq;
+
+ public int endSeq;
+
+ /**
* Property change listener for changes in alignment
*
* @param listener
setSequenceAnnotationsVisible(seq, true);
}
- hasHiddenRows = false;
hiddenRepSequences = null;
firePropertyChange("alignment", null, alignment.getSequences());
selectionGroup.addSequence(seq, false);
setSequenceAnnotationsVisible(seq, true);
}
- // JBPNote: refactor: only update flag if we modified visiblity (used to
- // do this regardless)
- if (alignment.getHiddenSequences().getSize() < 1)
- {
- hasHiddenRows = false;
- }
firePropertyChange("alignment", null, alignment.getSequences());
sendSelection();
}
alignment.getHiddenSequences().hideSequence(seq[i]);
setSequenceAnnotationsVisible(seq[i], false);
}
- hasHiddenRows = true;
firePropertyChange("alignment", null, alignment.getSequences());
}
}
* If this is a protein alignment and there are mappings to cDNA, add the cDNA
* consensus annotation.
*/
- protected void initComplementConsensus()
+ public void initComplementConsensus()
{
if (!alignment.isNucleotide())
{
@Override
public void setShowSequenceFeaturesHeight(boolean selected)
{
- viewStyle.setShowSeqFeaturesHeight(selected);
+ viewStyle.setShowSequenceFeaturesHeight(selected);
}
@Override
{
return viewStyle.isShowColourText();
}
- /**
- * @return
- * @see jalview.api.ViewStyleI#isShowSeqFeaturesHeight()
- */
- public boolean isShowSeqFeaturesHeight()
- {
- return viewStyle.isShowSeqFeaturesHeight();
- }
/**
* @param conservationColourSelected
{
this.showAutocalculatedAbove = showAutocalculatedAbove;
}
+
+ @Override
+ public boolean isScaleProteinAsCdna()
+ {
+ return viewStyle.isScaleProteinAsCdna();
+ }
+
+ @Override
+ public void setScaleProteinAsCdna(boolean b)
+ {
+ viewStyle.setScaleProteinAsCdna(b);
+ }
+
+ /**
+ * @return true if view should scroll to show the highlighted region of a
+ * sequence
+ * @return
+ */
+ @Override
+ public final boolean isFollowHighlight()
+ {
+ return followHighlight;
+ }
+
+ @Override
+ public final void setFollowHighlight(boolean b)
+ {
+ this.followHighlight = b;
+ }
+
+ public int getStartRes()
+ {
+ return startRes;
+ }
+
+ public int getEndRes()
+ {
+ return endRes;
+ }
+
+ public int getStartSeq()
+ {
+ return startSeq;
+ }
+
+ public void setStartRes(int res)
+ {
+ this.startRes = res;
+ }
+
+ public void setStartSeq(int seq)
+ {
+ this.startSeq = seq;
+ }
+
+ public void setEndRes(int res)
+ {
+ if (res > alignment.getWidth() - 1)
+ {
+ // log.System.out.println(" Corrected res from " + res + " to maximum " +
+ // (alignment.getWidth()-1));
+ res = alignment.getWidth() - 1;
+ }
+ if (res < 0)
+ {
+ res = 0;
+ }
+ this.endRes = res;
+ }
+
+ public void setEndSeq(int seq)
+ {
+ if (seq > alignment.getHeight())
+ {
+ seq = alignment.getHeight();
+ }
+ if (seq < 0)
+ {
+ seq = 0;
+ }
+ this.endSeq = seq;
+ }
+
+ public int getEndSeq()
+ {
+ return endSeq;
+ }
+
+ /**
+ * Helper method to populate the SearchResults with the location in the
+ * complementary alignment to scroll to, in order to match this one.
+ *
+ * @param sr
+ * the SearchResults to add to
+ * @return the offset (below top of visible region) of the matched sequence
+ */
+ protected int findComplementScrollTarget(SearchResults sr)
+ {
+ final AlignViewportI complement = getCodingComplement();
+ if (complement == null || !complement.isFollowHighlight())
+ {
+ return 0;
+ }
+ boolean iAmProtein = !getAlignment().isNucleotide();
+ AlignmentI proteinAlignment = iAmProtein ? getAlignment()
+ : complement.getAlignment();
+ if (proteinAlignment == null)
+ {
+ return 0;
+ }
+ final Set<AlignedCodonFrame> mappings = proteinAlignment
+ .getCodonFrames();
+
+ /*
+ * Heuristic: find the first mapped sequence (if any) with a non-gapped
+ * residue in the middle column of the visible region. Scroll the
+ * complementary alignment to line up the corresponding residue.
+ */
+ int seqOffset = 0;
+ SequenceI sequence = null;
+
+ /*
+ * locate 'middle' column (true middle if an odd number visible, left of
+ * middle if an even number visible)
+ */
+ int middleColumn = getStartRes() + (getEndRes() - getStartRes()) / 2;
+ final HiddenSequences hiddenSequences = getAlignment()
+ .getHiddenSequences();
+ for (int seqNo = getStartSeq(); seqNo < getEndSeq(); seqNo++, seqOffset++)
+ {
+ sequence = getAlignment().getSequenceAt(seqNo);
+ if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
+ {
+ continue;
+ }
+ if (Comparison.isGap(sequence.getCharAt(middleColumn)))
+ {
+ continue;
+ }
+ List<AlignedCodonFrame> seqMappings = MappingUtils
+ .findMappingsForSequence(sequence, mappings);
+ if (!seqMappings.isEmpty())
+ {
+ break;
+ }
+ }
+
+ if (sequence == null)
+ {
+ /*
+ * No ungapped mapped sequence in middle column - do nothing
+ */
+ return 0;
+ }
+ MappingUtils.addSearchResults(sr, sequence,
+ sequence.findPosition(middleColumn), mappings);
+ return seqOffset;
+ }
}