JAL-4071 first working prototype
[jalview.git] / src / jalview / workers / VisibleFeaturesAnnotationTracks.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.workers;
22
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
25 import java.util.Collections;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29
30 import jalview.api.AlignViewportI;
31 import jalview.api.FeaturesDisplayedI;
32 import jalview.datamodel.SequenceFeature;
33 import jalview.gui.FeatureRenderer;
34
35 public class VisibleFeaturesAnnotationTracks implements FeatureSetCounterI
36 {
37   AlignViewportI ourViewport = null;
38
39   jalview.api.FeatureRenderer ourFr = null;
40
41   PropertyChangeListener ourListener = new PropertyChangeListener()
42   {
43
44     @Override
45     public void propertyChange(PropertyChangeEvent evt)
46     {
47       if (ourViewport != null) // could check source is
48                                // ourFr.getChangeSupport...
49       {
50         updateFeatureAnnotationTracks();
51       }
52     }
53   };
54
55   public VisibleFeaturesAnnotationTracks(AlignViewportI viewport,
56           FeatureRenderer fr)
57   {
58     ourViewport = viewport;
59     ourFr = fr;
60     registerListener();
61   }
62
63   void registerListener()
64   {
65     ourFr.addPropertyChangeListener(ourListener);
66   }
67
68   public void tidyUp()
69   {
70     if (ourFr != null)
71     {
72       ourFr.removePropertyChangeListener(ourListener);
73     }
74     if (ourViewport != null && ourViewport.getCalcManager() != null)
75     {
76       if (ourWorker != null)
77       {
78         ourWorker.abortAndDestroy();
79         ourViewport.getCalcManager()
80                 .removeRegisteredWorkersOfClass(ourWorker.getClass());
81       }
82       ourWorker = null;
83       ourViewport = null;
84     }
85   }
86
87   public void updateFeatureAnnotationTracks()
88   {
89     // if tracks are turned off, this returns null.
90     FeaturesDisplayedI featuresDisp = ourViewport
91             .isShowSequenceFeatureCounts()
92                     ? ourViewport.getFeaturesDisplayed()
93                     : null;
94     Set<String> visibleFeatures = new HashSet();
95     if (featuresDisp != null)
96     {
97       visibleFeatures.addAll(featuresDisp.getVisibleFeatures());
98     }
99     if (dispFeatures.equals(visibleFeatures))
100     {
101       // all the same features displayed
102       return;
103     }
104     // otherwise set up tracks accordingly
105
106     /*
107      * and register the counter
108      */
109     if (ourWorker != null)
110     {
111       Set<String> toRemove = new HashSet<String>(),
112               toAdd = new HashSet<String>();
113       toRemove.addAll(dispFeatures);
114       toRemove.removeAll(visibleFeatures);
115       dispFeatures = visibleFeatures;
116       ourWorker.removeOldAnnotations(toRemove.toArray(new String[0]));
117
118     }
119     else
120     {
121       dispFeatures = visibleFeatures;
122       ourWorker = new ColumnCounterSetWorker(ourViewport,
123               ourFr.getAlignPanel(), this);
124     }
125     ourViewport.getCalcManager().registerWorker(ourWorker);
126     ourViewport.getCalcManager().startWorker(ourWorker);
127   }
128
129   ColumnCounterSetWorker ourWorker = null;
130
131   Set<String> dispFeatures = Collections.EMPTY_SET;
132
133   @Override
134   public int[] count(String residue, List<SequenceFeature> features)
135   {
136     final Set<String> ourDispFeatures = dispFeatures;
137     int[] obs = new int[ourDispFeatures.size()];
138     SequenceFeature[] sfs = features.toArray(new SequenceFeature[0]);
139     for (SequenceFeature sf : sfs)
140     {
141       /*
142        * Here we inspect the type of the sequence feature.
143        * You can also test sf.description, sf.score, sf.featureGroup,
144        * sf.strand, sf.phase, sf.begin, sf.end
145        * or sf.getValue(attributeName) for GFF 'column 9' properties
146        */
147       int pos = 0;
148       for (String type : ourDispFeatures)
149       {
150         if (type.equals(sf.type))
151         {
152           obs[pos]++;
153         }
154         pos++;
155       }
156     }
157     return obs;
158   }
159
160   @Override
161   public String[] getNames()
162   {
163     return dispFeatures.toArray(new String[0]);
164   }
165
166   @Override
167   public String[] getDescriptions()
168   {
169     return dispFeatures.toArray(new String[0]);
170   }
171
172   @Override
173   public int[] getMaxColour()
174   {
175     return new int[] { 0, 0, 255 };
176   }
177
178   @Override
179   public int[] getMinColour()
180   {
181     return new int[] { 0, 255, 255 };
182   }
183 }