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