}
sg.setEndRes(viewport.getAlignment().getWidth() - 1);
viewport.setSelectionGroup(sg);
- alignPanel.paintAlignment(true);
+ // JAL-2034 - should delegate to
+ // alignPanel to decide if overview needs
+ // updating.
+ alignPanel.paintAlignment(false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
viewport.setSelectionGroup(null);
alignPanel.idPanel.idCanvas.searchResults = null;
alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);
- alignPanel.paintAlignment(true);
+ // JAL-2034 - should delegate to
+ // alignPanel to decide if overview needs
+ // updating.
+ alignPanel.paintAlignment(false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
AlignmentI alignment = av.getAlignment();
for (row = 0; row <= sequencesHeight; row++)
{
+ if (resizeAgain)
+ {
+ break;
+ }
if ((int) (row * sampleRow) == lastrow)
{
sameRow++;
{
for (col = 0; col < width; col++)
{
+ if (resizeAgain)
+ {
+ break;
+ }
lastcol = (int) (col * sampleCol);
{
mg.translate(col, sequencesHeight);
Tooltip tooltip;
+ /**
+ * set when the current UI interaction has resulted in a change that requires
+ * overview shading to be recalculated. this could be changed to something
+ * more expressive that indicates what actually has changed, so selective
+ * redraws can be applied
+ */
+ private boolean needOverviewUpdate; // TODO: refactor to avcontroller
+
+ /**
+ * set if av.getSelectionGroup() refers to a group that is defined on the
+ * alignment view, rather than a transient selection
+ */
+ private boolean editingDefinedGroup = false; // TODO: refactor to avcontroller
+ // or viewModel
+
@Override
public void mouseDragged(MouseEvent evt)
{
&& res < stretchGroup.getEndRes())
{
av.setSelectionGroup(stretchGroup);
+ editingDefinedGroup = true;
}
else
{
stretchGroup = null;
+ editingDefinedGroup = false;
}
}
&& allGroups[i].getEndRes() >= res)
{
stretchGroup = allGroups[i];
+ editingDefinedGroup = true;
break;
}
}
sg.setEndRes(res);
sg.addSequence(sequence, false);
av.setSelectionGroup(sg);
+ editingDefinedGroup = false;
stretchGroup = sg;
if (av.getConservationSelected())
{
return;
}
-
- stretchGroup.recalcConservation(); // always do this - annotation has own
- // state
+ // always do this - annotation has own state
+ // but defer colourscheme update until hidden sequences are passed in
+ boolean vischange = stretchGroup.recalcConservation(true);
+ needOverviewUpdate |= vischange && editingDefinedGroup;
if (stretchGroup.cs != null)
{
stretchGroup.cs.alignmentChanged(stretchGroup,
stretchGroup.getName());
}
}
+ PaintRefresher.Refresh(ap, av.getSequenceSetId());
+ ap.paintAlignment(needOverviewUpdate);
+ needOverviewUpdate =false;
+ editingDefinedGroup = false;
changeEndRes = false;
changeStartRes = false;
stretchGroup = null;
- PaintRefresher.Refresh(ap, av.getSequenceSetId());
- ap.paintAlignment(true);
av.sendSelection();
}
if (res > (stretchGroup.getStartRes() - 1))
{
stretchGroup.setEndRes(res);
+ needOverviewUpdate |= editingDefinedGroup;
}
}
else if (changeStartRes)
if (res < (stretchGroup.getEndRes() + 1))
{
stretchGroup.setStartRes(res);
+ needOverviewUpdate |= editingDefinedGroup;
}
}
if (stretchGroup.getSequences(null).contains(nextSeq))
{
stretchGroup.deleteSequence(seq, false);
+ needOverviewUpdate |= editingDefinedGroup;
}
else
{
}
stretchGroup.addSequence(nextSeq, false);
+ needOverviewUpdate |= editingDefinedGroup;
}
}
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
-import java.util.Vector;
/**
* Transient object compactly representing a 'view' of an alignment - with
*/
private class ScGroup
{
- public Vector seqs;
+ public List<SeqCigar> seqs;
public SequenceGroup sg;
ScGroup()
{
- seqs = new Vector();
+ seqs = new ArrayList<SeqCigar>();
+ }
+
+ /**
+ * @param seq
+ * @return true if seq was not a member before and was added to group
+ */
+ public boolean add(SeqCigar seq)
+ {
+ if (!seq.isMemberOf(this))
+ {
+ seqs.add(seq);
+ seq.setGroupMembership(this);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param seq
+ * @return true if seq was a member and was removed from group
+ */
+ public boolean remove(SeqCigar seq)
+ {
+ if (seq.removeGroupMembership(this))
+ {
+ seqs.remove(seq);
+ return true;
+ }
+ return false;
+ }
+
+ public int size()
+ {
+ return seqs.size();
}
}
* vector of selected seqCigars. This vector is also referenced by each
* seqCigar contained in it.
*/
- private Vector selected;
+ private ScGroup selected;
/**
* Construct an alignmentView from a live jalview alignment view. Note -
if (selection != null && selection.getSize() > 0)
{
List<SequenceI> sel = selection.getSequences(null);
- this.selected = new Vector();
+ this.selected = new ScGroup();
selseqs = selection
.getSequencesInOrder(alignment, selectedRegionOnly);
}
if (selection != null && selection.getSize() > 0
&& !selectedRegionOnly)
{
- sequences[csi].setGroupMembership(selected);
- selected.addElement(sequences[csi]);
+ selected.add(sequences[csi]);
}
if (seqsets != null)
{
{
if ((seqsets.get(sg)).contains(selseqs[i]))
{
- sequences[csi].setGroupMembership(sgrps[sg]);
sgrps[sg].sg.deleteSequence(selseqs[i], false);
- sgrps[sg].seqs.addElement(sequences[csi]);
+ sgrps[sg].add(sequences[csi]);
if (!addedgps[sg])
{
if (scGroups == null)
+ sgr.sg.getEndRes());
for (int s = 0; s < sgr.seqs.size(); s++)
{
- if (!((SeqCigar) sgr.seqs.elementAt(s)).isMemberOf(sgr))
+ // JBPnote this should be a unit test for ScGroup
+ if (!sgr.seqs.get(s).isMemberOf(sgr))
{
- os.println("** WARNING: sequence "
- + ((SeqCigar) sgr.seqs.elementAt(s)).toString()
+ os.println("** WARNING: sequence " + sgr.seqs.get(s).toString()
+ " is not marked as member of group.");
}
}
}
/**
- * calculate residue conservation for group - but only if necessary.
+ * calculate residue conservation and colourschemes for group - but only if
+ * necessary. returns true if the calculation resulted in a visible change to
+ * group
*/
- public void recalcConservation()
+ public boolean recalcConservation()
+ {
+ return recalcConservation(false);
+ }
+
+ /**
+ * calculate residue conservation for group - but only if necessary. returns
+ * true if the calculation resulted in a visible change to group
+ *
+ * @param defer
+ * when set, colourschemes for this group are not refreshed after
+ * recalculation
+ */
+ public boolean recalcConservation(boolean defer)
{
if (cs == null && consensus == null && conservation == null)
{
- return;
+ return false;
}
+ // TODO: try harder to detect changes in state in order to minimise
+ // recalculation effort
try
{
Hashtable cnsns[] = AAFrequency.calculate(sequences, startRes,
}
}
}
- if (cs != null)
+ if (cs != null && !defer)
{
+ // TODO: JAL-2034 should cs.alignmentChanged modify return state
cs.alignmentChanged(context != null ? context : this, null);
+ return true;
+ }
+ else
+ {
+ return false;
}
} catch (java.lang.OutOfMemoryError err)
{
// TODO: catch OOM
System.out.println("Out of memory loading groups: " + err);
}
-
+ return false;
}
private void _updateConservationRow(Conservation c)
sg.setEndRes(viewport.getAlignment().getWidth() - 1);
viewport.setSelectionGroup(sg);
viewport.sendSelection();
- alignPanel.paintAlignment(true);
+ // JAL-2034 - should delegate to
+ // alignPanel to decide if overview needs
+ // updating.
+ alignPanel.paintAlignment(false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
}
viewport.setSelectionGroup(null);
alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(null);
alignPanel.getIdPanel().getIdCanvas().searchResults = null;
- alignPanel.paintAlignment(true);
+ // JAL-2034 - should delegate to
+ // alignPanel to decide if overview needs
+ // updating.
+ alignPanel.paintAlignment(false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
{
sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
}
+ // JAL-2034 - should delegate to
+ // alignPanel to decide if overview needs
+ // updating.
alignPanel.paintAlignment(true);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
final boolean hasHiddenRows = av.hasHiddenRows(), hasHiddenCols = av
.hasHiddenColumns();
boolean hiddenRow = false;
+ // get hidden row and hidden column map once at beginning.
+ // clone featureRenderer settings to avoid race conditions... if state is
+ // updated just need to refresh again
for (row = 0; row < sequencesHeight; row++)
{
+ if (resizeAgain)
+ {
+ break;
+ }
if ((int) (row * sampleRow) == lastrow)
{
// No need to recalculate the colours,
// Just copy from the row above
for (col = 0; col < width; col++)
{
+ if (resizeAgain)
+ {
+ break;
+ }
miniMe.setRGB(col, row, miniMe.getRGB(col, row - 1));
}
continue;
for (col = 0; col < width; col++)
{
+ if (resizeAgain)
+ {
+ break;
+ }
if ((int) (col * sampleCol) == lastcol
&& (int) (row * sampleRow) == lastrow)
{
renderer.updateFromAlignViewport(av);
for (col = 0; col < width; col++)
{
+ if (resizeAgain)
+ {
+ break;
+ }
lastcol = (int) (col * sampleCol);
{
mg.translate(col, sequencesHeight);
String lastTooltip;
/**
+ * set when the current UI interaction has resulted in a change that requires
+ * overview shading to be recalculated. this could be changed to something
+ * more expressive that indicates what actually has changed, so selective
+ * redraws can be applied
+ */
+ private boolean needOverviewUpdate = false; // TODO: refactor to avcontroller
+
+ /**
+ * set if av.getSelectionGroup() refers to a group that is defined on the
+ * alignment view, rather than a transient selection
+ */
+ private boolean editingDefinedGroup = false; // TODO: refactor to avcontroller or viewModel
+
+ /**
* Set status message in alignment panel
*
* @param sequence
&& (res < stretchGroup.getEndRes()))
{
av.setSelectionGroup(stretchGroup);
+ editingDefinedGroup = true;
}
else
{
stretchGroup = null;
+ editingDefinedGroup = false;
}
}
else if (!stretchGroup.getSequences(null).contains(sequence)
&& (allGroups[i].getEndRes() >= res))
{
stretchGroup = allGroups[i];
+ editingDefinedGroup = true;
break;
}
}
sg.setEndRes(res);
sg.addSequence(sequence, false);
av.setSelectionGroup(sg);
-
+ editingDefinedGroup = false;
stretchGroup = sg;
if (av.getConservationSelected())
{
return;
}
-
- stretchGroup.recalcConservation(); // always do this - annotation has own
- // state
+ // always do this - annotation has own state
+ // but defer colourscheme update until hidden sequences are passed in
+ boolean vischange = stretchGroup.recalcConservation(true);
+ needOverviewUpdate |= vischange && editingDefinedGroup;
if (stretchGroup.cs != null)
{
stretchGroup.cs.alignmentChanged(stretchGroup,
}
}
PaintRefresher.Refresh(this, av.getSequenceSetId());
- ap.paintAlignment(true);
-
+ ap.paintAlignment(needOverviewUpdate);
+ needOverviewUpdate =false;
+ editingDefinedGroup = false;
changeEndRes = false;
changeStartRes = false;
stretchGroup = null;
if (res > (stretchGroup.getStartRes() - 1))
{
stretchGroup.setEndRes(res);
+ needOverviewUpdate |= editingDefinedGroup;
}
}
else if (changeStartRes)
if (res < (stretchGroup.getEndRes() + 1))
{
stretchGroup.setStartRes(res);
+ needOverviewUpdate |= editingDefinedGroup;
}
}
if (stretchGroup.getSequences(null).contains(nextSeq))
{
stretchGroup.deleteSequence(seq, false);
+ needOverviewUpdate |= editingDefinedGroup;
}
else
{
}
stretchGroup.addSequence(nextSeq, false);
+ needOverviewUpdate |= editingDefinedGroup;
}
}
@Override
public Color getResidueBoxColour(SequenceI seq, int i)
{
+ // rate limiting step when rendering overview for lots of groups
allGroups = av.getAlignment().findAllGroups(seq);
if (inCurrentSequenceGroup(i))