*/
package jalview.api;
-import jalview.datamodel.MappedFeatures;
-import jalview.datamodel.SequenceFeature;
-import jalview.datamodel.SequenceI;
-import jalview.datamodel.features.FeatureMatcherSetI;
-
import java.awt.Color;
import java.awt.Graphics;
+import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.Map;
+import jalview.datamodel.MappedFeatures;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.features.FeatureMatcherSetI;
+
/**
* Abstract feature renderer interface
*
*/
void notifyFeaturesChanged();
+ /**
+ * register as a listener for notifyFeaturesChanged events
+ *
+ * @param ourListener
+ */
+ void addPropertyChangeListener(PropertyChangeListener ourListener);
+
+ /**
+ * remove a listener for notifyFeaturesChanged events
+ *
+ * @param ourListener
+ */
+ void removePropertyChangeListener(PropertyChangeListener ourListener);
+
+ /**
+ *
+ * @return associated alignment panel for this feature renderer (may return
+ * null)
+ */
+ AlignmentViewPanel getAlignPanel();
+
}
*/
package jalview.gui;
-import jalview.analysis.AnnotationSorter;
-import jalview.api.AlignViewportI;
-import jalview.api.AlignmentViewPanel;
-import jalview.bin.Cache;
-import jalview.bin.Console;
-import jalview.bin.Jalview;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.SearchResultsI;
-import jalview.datamodel.SequenceFeature;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.gui.ImageExporter.ImageWriterI;
-import jalview.io.HTMLOutput;
-import jalview.jbgui.GAlignmentPanel;
-import jalview.math.AlignmentDimension;
-import jalview.schemes.ResidueProperties;
-import jalview.structure.StructureSelectionManager;
-import jalview.util.Comparison;
-import jalview.util.ImageMaker;
-import jalview.util.MessageManager;
-import jalview.viewmodel.ViewportListenerI;
-import jalview.viewmodel.ViewportRanges;
-
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import javax.swing.SwingUtilities;
+import jalview.analysis.AnnotationSorter;
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
+import jalview.bin.Cache;
+import jalview.bin.Console;
+import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.SearchResultsI;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.ImageExporter.ImageWriterI;
+import jalview.io.HTMLOutput;
+import jalview.jbgui.GAlignmentPanel;
+import jalview.math.AlignmentDimension;
+import jalview.schemes.ResidueProperties;
+import jalview.structure.StructureSelectionManager;
+import jalview.util.Comparison;
+import jalview.util.ImageMaker;
+import jalview.util.MessageManager;
+import jalview.viewmodel.ViewportListenerI;
+import jalview.viewmodel.ViewportRanges;
+import jalview.workers.VisibleFeaturesAnnotationTracks;
+
/**
* DOCUMENT ME!
*
private CalculationChooser calculationDialog;
+ private VisibleFeaturesAnnotationTracks featureCounter;
+
/**
* Creates a new AlignmentPanel object.
*
setIdPanel(new IdPanel(av, this));
setScalePanel(new ScalePanel(av, this));
+ featureCounter = new VisibleFeaturesAnnotationTracks(av,
+ seqPanel.seqCanvas.fr);
idPanelHolder.add(getIdPanel(), BorderLayout.CENTER);
idwidthAdjuster = new IdwidthAdjuster(this);
});
final AlignmentPanel ap = this;
+
propertyChangeListener = new PropertyChangeListener()
{
@Override
public void paintAlignment(boolean updateOverview,
boolean updateStructures)
{
+ featureCounter.updateFeatureAnnotationTracks();
final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
av.isShowAutocalculatedAbove());
sorter.sort(getAlignment().getAlignmentAnnotation(),
annotationPanel = null;
}
+ if (featureCounter != null)
+ {
+ featureCounter.tidyUp();
+ featureCounter = null;
+ }
if (av != null)
{
av.removePropertyChangeListener(propertyChangeListener);
*/
package jalview.gui;
+import jalview.api.AlignmentViewPanel;
+
/**
* A class that manages drawing of sequence features for the Swing gui
*/
{
super(alignPanel.av);
this.ap = alignPanel;
+
if (alignPanel.getSeqPanel() != null
&& alignPanel.getSeqPanel().seqCanvas != null
&& alignPanel.getSeqPanel().seqCanvas.fr != null)
transferSettings(alignPanel.getSeqPanel().seqCanvas.fr);
}
}
+
+ @Override
+ public AlignmentViewPanel getAlignPanel()
+ {
+ return ap;
+ }
}
*/
List<SequenceFeature> overlaps = seq.findFeatures(column, column,
type);
- for (int i = overlaps.size() - 1 ; i >= 0 ; i--)
+ for (int i = overlaps.size() - 1; i >= 0; i--)
{
SequenceFeature sequenceFeature = overlaps.get(i);
if (!featureGroupNotShown(sequenceFeature))
import java.util.concurrent.ConcurrentHashMap;
import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
import jalview.api.FeatureColourI;
import jalview.api.FeaturesDisplayedI;
import jalview.datamodel.AlignedCodonFrame;
* @param listener
* @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener)
*/
+ @Override
public void addPropertyChangeListener(PropertyChangeListener listener)
{
changeSupport.addPropertyChangeListener(listener);
* @param listener
* @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener)
*/
+ @Override
public void removePropertyChangeListener(PropertyChangeListener listener)
{
changeSupport.removePropertyChangeListener(listener);
}
return true;
}
+
+ @Override
+ public AlignmentViewPanel getAlignPanel()
+ {
+ return null;
+ }
}
setShowNPFeats(vs.isShowNPFeats());
setShowSequenceFeaturesHeight(vs.isShowSequenceFeaturesHeight());
setShowSequenceFeatures(vs.isShowSequenceFeatures());
+ setShowSequenceFeatureCounts(vs.isShowSequenceFeatureCounts());
setShowComplementFeatures(vs.isShowComplementFeatures());
setShowComplementFeaturesOnTop(vs.isShowComplementFeaturesOnTop());
setShowText(vs.getShowText());
&& isShowNPFeats() == vs.isShowNPFeats()
&& isShowSequenceFeaturesHeight() == vs
.isShowSequenceFeaturesHeight()
+ && isShowSequenceFeatureCounts() == vs
+ .isShowSequenceFeatureCounts()
&& isShowSequenceFeatures() == vs.isShowSequenceFeatures()
&& isShowComplementFeatures() == vs.isShowComplementFeatures()
&& isShowComplementFeaturesOnTop() == vs
*/
package jalview.workers;
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.List;
+
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.datamodel.AlignmentAnnotation;
import jalview.util.ColorUtils;
import jalview.util.Comparison;
-import java.awt.Color;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* A class to compute alignment annotations with column counts for a set of
* properties of interest on positions in an alignment. <br>
return annotationAdded;
}
+ void removeOldAnnotations(String[] annotDescs)
+ {
+ // TODO use the commented out code once JAL-2075 is fixed
+ // to get adequate performance on genomic length sequence
+ AlignmentI alignment = alignViewport.getAlignment();
+ ArrayList<AlignmentAnnotation> toRemove = new ArrayList<AlignmentAnnotation>();
+ for (String toRemoveDesc : annotDescs)
+ {
+ for (AlignmentAnnotation aa : ourAnnots)
+ {
+ if (toRemoveDesc.equals(aa.getCalcId()))
+ toRemove.add(aa);
+ }
+ }
+ for (AlignmentAnnotation deleted : toRemove)
+ {
+ alignment.deleteAnnotation(deleted);
+ }
+ }
+
/**
* Returns a count of any feature types present at the specified position of
* the alignment
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.workers;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import jalview.api.AlignViewportI;
+import jalview.api.FeaturesDisplayedI;
+import jalview.datamodel.SequenceFeature;
+import jalview.gui.FeatureRenderer;
+
+public class VisibleFeaturesAnnotationTracks implements FeatureSetCounterI
+{
+ AlignViewportI ourViewport = null;
+
+ jalview.api.FeatureRenderer ourFr = null;
+
+ PropertyChangeListener ourListener = new PropertyChangeListener()
+ {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt)
+ {
+ if (ourViewport != null) // could check source is
+ // ourFr.getChangeSupport...
+ {
+ updateFeatureAnnotationTracks();
+ }
+ }
+ };
+
+ public VisibleFeaturesAnnotationTracks(AlignViewportI viewport,
+ FeatureRenderer fr)
+ {
+ ourViewport = viewport;
+ ourFr = fr;
+ registerListener();
+ }
+
+ void registerListener()
+ {
+ ourFr.addPropertyChangeListener(ourListener);
+ }
+
+ public void tidyUp()
+ {
+ if (ourFr != null)
+ {
+ ourFr.removePropertyChangeListener(ourListener);
+ }
+ if (ourViewport != null && ourViewport.getCalcManager() != null)
+ {
+ if (ourWorker != null)
+ {
+ ourWorker.abortAndDestroy();
+ ourViewport.getCalcManager()
+ .removeRegisteredWorkersOfClass(ourWorker.getClass());
+ }
+ ourWorker = null;
+ ourViewport = null;
+ }
+ }
+
+ public void updateFeatureAnnotationTracks()
+ {
+ // if tracks are turned off, this returns null.
+ FeaturesDisplayedI featuresDisp = ourViewport
+ .isShowSequenceFeatureCounts()
+ ? ourViewport.getFeaturesDisplayed()
+ : null;
+ Set<String> visibleFeatures = new HashSet();
+ if (featuresDisp != null)
+ {
+ visibleFeatures.addAll(featuresDisp.getVisibleFeatures());
+ }
+ if (dispFeatures.equals(visibleFeatures))
+ {
+ // all the same features displayed
+ return;
+ }
+ // otherwise set up tracks accordingly
+
+ /*
+ * and register the counter
+ */
+ if (ourWorker != null)
+ {
+ Set<String> toRemove = new HashSet<String>(),
+ toAdd = new HashSet<String>();
+ toRemove.addAll(dispFeatures);
+ toRemove.removeAll(visibleFeatures);
+ dispFeatures = visibleFeatures;
+ ourWorker.removeOldAnnotations(toRemove.toArray(new String[0]));
+
+ }
+ else
+ {
+ dispFeatures = visibleFeatures;
+ ourWorker = new ColumnCounterSetWorker(ourViewport,
+ ourFr.getAlignPanel(), this);
+ }
+ ourViewport.getCalcManager().registerWorker(ourWorker);
+ ourViewport.getCalcManager().startWorker(ourWorker);
+ }
+
+ ColumnCounterSetWorker ourWorker = null;
+
+ Set<String> dispFeatures = Collections.EMPTY_SET;
+
+ @Override
+ public int[] count(String residue, List<SequenceFeature> features)
+ {
+ final Set<String> ourDispFeatures = dispFeatures;
+ int[] obs = new int[ourDispFeatures.size()];
+ SequenceFeature[] sfs = features.toArray(new SequenceFeature[0]);
+ for (SequenceFeature sf : sfs)
+ {
+ /*
+ * Here we inspect the type of the sequence feature.
+ * You can also test sf.description, sf.score, sf.featureGroup,
+ * sf.strand, sf.phase, sf.begin, sf.end
+ * or sf.getValue(attributeName) for GFF 'column 9' properties
+ */
+ int pos = 0;
+ for (String type : ourDispFeatures)
+ {
+ if (type.equals(sf.type))
+ {
+ obs[pos]++;
+ }
+ pos++;
+ }
+ }
+ return obs;
+ }
+
+ @Override
+ public String[] getNames()
+ {
+ return dispFeatures.toArray(new String[0]);
+ }
+
+ @Override
+ public String[] getDescriptions()
+ {
+ return dispFeatures.toArray(new String[0]);
+ }
+
+ @Override
+ public int[] getMaxColour()
+ {
+ return new int[] { 0, 0, 255 };
+ }
+
+ @Override
+ public int[] getMinColour()
+ {
+ return new int[] { 0, 255, 255 };
+ }
+}
\ No newline at end of file