JAL-1517 fix copyright for 2.8.2
[jalview.git] / src / jalview / controller / AlignViewController.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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.controller;
22
23 import java.awt.Color;
24 import java.util.BitSet;
25 import java.util.List;
26
27 import jalview.api.AlignViewControllerGuiI;
28 import jalview.api.AlignViewControllerI;
29 import jalview.api.AlignViewportI;
30 import jalview.api.AlignmentViewPanel;
31 import jalview.datamodel.AlignmentI;
32 import jalview.datamodel.AnnotatedCollectionI;
33 import jalview.datamodel.ColumnSelection;
34 import jalview.datamodel.SequenceCollectionI;
35 import jalview.datamodel.SequenceFeature;
36 import jalview.datamodel.SequenceGroup;
37 import jalview.datamodel.SequenceI;
38
39 public class AlignViewController implements AlignViewControllerI
40 {
41   AlignViewportI viewport=null;
42   AlignmentViewPanel alignPanel=null;
43   /**
44    * the GUI container that is handling interactions with the user
45    */
46   private AlignViewControllerGuiI avcg;
47   @Override
48   protected void finalize() throws Throwable {
49     viewport = null;
50     alignPanel = null;
51     avcg = null;
52   };
53   
54   public AlignViewController(AlignViewControllerGuiI alignFrame, AlignViewportI viewport,
55           AlignmentViewPanel alignPanel)
56   {
57     this.avcg = alignFrame;
58     this.viewport=viewport;
59     this.alignPanel = alignPanel;
60   }
61   @Override
62   public void setViewportAndAlignmentPanel(AlignViewportI viewport,AlignmentViewPanel alignPanel)
63   {
64     this.alignPanel = alignPanel;
65     this.viewport = viewport;
66     
67   }
68   @Override
69   public boolean makeGroupsFromSelection()
70   {
71
72     if (viewport.getSelectionGroup() != null)
73     {
74       SequenceGroup[] gps = jalview.analysis.Grouping.makeGroupsFrom(
75               viewport.getSequenceSelection(),
76               viewport.getAlignmentView(true).getSequenceStrings(
77                       viewport.getGapCharacter()), viewport.getAlignment()
78                       .getGroups());
79       viewport.getAlignment().deleteAllGroups();
80       viewport.clearSequenceColours();
81       viewport.setSelectionGroup(null);
82       // set view properties for each group
83       for (int g = 0; g < gps.length; g++)
84       {
85         // gps[g].setShowunconserved(viewport.getShowUnconserved());
86         gps[g].setshowSequenceLogo(viewport.isShowSequenceLogo());
87         viewport.getAlignment().addGroup(gps[g]);
88         Color col = new Color((int) (Math.random() * 255),
89                 (int) (Math.random() * 255), (int) (Math.random() * 255));
90         col = col.brighter();
91         for (SequenceI sq : gps[g].getSequences(null))
92           viewport.setSequenceColour(sq, col);
93       }
94       return true;
95     }
96     return false;
97 }
98   @Override
99   public boolean createGroup()
100   {
101
102     SequenceGroup sg = viewport.getSelectionGroup();
103     if (sg!=null)
104     {
105         viewport.getAlignment().addGroup(sg);
106         return true;
107       } 
108     return false;
109   }
110   @Override
111   public boolean unGroup()
112   {
113     SequenceGroup sg = viewport.getSelectionGroup();
114     if (sg!=null)
115     {
116         viewport.getAlignment().deleteGroup(sg);
117         return true;
118     }
119     return false;
120   }
121   @Override
122   public boolean deleteGroups()
123   {
124     if (viewport.getAlignment().getGroups()!=null && viewport.getAlignment().getGroups().size()>0)
125     {
126     viewport.getAlignment().deleteAllGroups();
127     viewport.clearSequenceColours();
128     viewport.setSelectionGroup(null);
129     return true;
130     }
131     return false;
132   }
133    
134   @Override
135   public boolean markColumnsContainingFeatures(boolean invert, boolean extendCurrent, boolean toggle, String featureType)
136   {
137     // JBPNote this routine could also mark rows, not just columns.
138     // need a decent query structure to allow all types of feature searches
139     BitSet bs = new BitSet();
140     int alw,alStart;
141     SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null ? viewport.getAlignment() : viewport.getSelectionGroup()); 
142     alStart = sqcol.getStartRes();
143     alw = sqcol.getEndRes()+1;
144     List<SequenceI> seqs = sqcol.getSequences();
145     int nseq = 0;
146     for (SequenceI sq : seqs)
147     {
148       int tfeat = 0;
149       if (sq != null)
150       {
151         SequenceI dsq = sq.getDatasetSequence();
152         while (dsq.getDatasetSequence() != null)
153         {
154           dsq = dsq.getDatasetSequence();
155         }
156         ;
157         SequenceFeature[] sf = dsq.getSequenceFeatures();
158         if (sf != null)
159         {
160           int ist = sq.findIndex(sq.getStart());
161           int iend = sq.findIndex(sq.getEnd());
162           if (iend < alStart || ist> alw)
163           {
164             // sequence not in region
165             continue;
166           }
167           for (SequenceFeature sfpos : sf)
168           {
169             // future functionalty - featureType == null means mark columns
170             // containing all displayed features
171             if (sfpos != null && (featureType.equals(sfpos.getType())))
172             {
173               tfeat++;
174               // optimisation - could consider 'spos,apos' like cursor argument
175               // - findIndex wastes time by starting from first character and
176               // counting
177
178               int i = sq.findIndex(sfpos.getBegin());
179               int j = sq.findIndex(sfpos.getEnd());
180               if (j<alStart || i>alw)
181               {
182                 // feature is outside selected region
183                 continue;
184               }
185               if (i < alStart)
186               {
187                 i = alStart;
188               }
189               if (i< ist) {
190                 i = ist;
191               }
192               if (j > alw)
193               {
194                 j = alw;
195               }
196               for (; i <= j; i++)
197               {
198                 bs.set(i - 1);
199               }
200             }
201           }
202         }
203
204         if (tfeat > 0)
205         {
206           nseq++;
207         }
208       }
209     }
210     ColumnSelection cs = viewport.getColumnSelection();
211     if (bs.cardinality() > 0 || invert)
212     {
213       if (cs == null)
214       {
215         cs = new ColumnSelection();
216       } else {
217         if (!extendCurrent)
218         {
219           cs.clear();
220         }
221       }
222       if (invert)
223       {
224         // invert only in the currently selected sequence region
225         for (int i = bs.nextClearBit(alStart), ibs = bs.nextSetBit(alStart); i >= alStart
226                 && i < (alw);)
227         {
228           if (ibs < 0 || i < ibs)
229           {
230             if (toggle && cs.contains(i))
231               {
232                 cs.removeElement(i++);
233               } else 
234               {
235                 cs.addElement(i++);
236               }
237           }
238           else
239           {
240             i = bs.nextClearBit(ibs);
241             ibs = bs.nextSetBit(i);
242           }
243         }
244       }
245       else
246       {
247         for (int i = bs.nextSetBit(alStart); i >= alStart; i = bs.nextSetBit(i + 1))
248         {
249           if (toggle && cs.contains(i))
250           {
251             cs.removeElement(i);
252           } else 
253           {
254             cs.addElement(i);
255           }
256         }
257       }
258       viewport.setColumnSelection(cs);
259       alignPanel.paintAlignment(true);
260       avcg.setStatus((toggle ? "Toggled ": "Marked ")
261               + (invert ? (alw-alStart) - bs.cardinality() : bs.cardinality())
262               + " columns "+(invert ? "not " : "") + "containing features of type " + featureType
263               + " across " + nseq + " sequence(s)");
264       return true;
265     }
266     else
267     {
268       avcg.setStatus("No features of type " + featureType + " found.");
269       if (!extendCurrent && cs!=null)
270       {
271         cs.clear();
272         alignPanel.paintAlignment(true);
273       }
274       return false;
275     }
276   }
277 }