Formatted source
[jalview.git] / src / jalview / gui / Finder.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import java.util.*;\r
22 \r
23 import java.awt.*;\r
24 import java.awt.event.*;\r
25 import javax.swing.*;\r
26 import javax.swing.event.*;\r
27 \r
28 import jalview.datamodel.*;\r
29 import jalview.jbgui.*;\r
30 \r
31 public class Finder\r
32     extends GFinder\r
33 {\r
34   AlignViewport av;\r
35   AlignmentPanel ap;\r
36   JInternalFrame frame;\r
37   SuperGroup searchGroup;\r
38   Vector searchResults;\r
39   int seqIndex = 0;\r
40   int resIndex = 0;\r
41 \r
42   public Finder(AlignViewport av, AlignmentPanel ap, JInternalFrame f)\r
43   {\r
44     this.av = av;\r
45     this.ap = ap;\r
46     frame = f;\r
47 \r
48     // all a big pain, but we need to wait until the frame is visible before the textfield can\r
49     // obtain the focus/////////////////////////\r
50     frame.addInternalFrameListener(new InternalFrameAdapter()\r
51     {\r
52       public void internalFrameOpened(InternalFrameEvent evt)\r
53       {\r
54         SwingUtilities.invokeLater(new Runnable()\r
55         {\r
56           public void run()\r
57           {\r
58             textfield.requestFocus();\r
59           }\r
60         });\r
61       }\r
62 \r
63       public void internalFrameClosing(InternalFrameEvent evt)\r
64       {\r
65         cancel_actionPerformed(null);\r
66       }\r
67     });\r
68   }\r
69 \r
70   public void textfield_actionPerformed(ActionEvent e)\r
71   {\r
72     doSearch(false);\r
73   }\r
74 \r
75   public void findNext_actionPerformed(ActionEvent e)\r
76   {\r
77     doSearch(false);\r
78   }\r
79 \r
80   public void findAll_actionPerformed(ActionEvent e)\r
81   {\r
82     resIndex = 0;\r
83     seqIndex = 0;\r
84     doSearch(true);\r
85   }\r
86 \r
87   public void cancel_actionPerformed(ActionEvent e)\r
88   {\r
89     try\r
90     {\r
91       // if allResults is null, this effectively switches displaySearch flag in seqCanvas\r
92       ap.highlightSearchResults(null);\r
93       ap.idPanel.highlightSearchResults(null);\r
94 \r
95       // frame.setClosed(true);\r
96     }\r
97     catch (Exception ex)\r
98     {\r
99     }\r
100   }\r
101 \r
102   public void createNewGroup_actionPerformed(ActionEvent e)\r
103   {\r
104     Color[] newColors = new Color[24];\r
105 \r
106     for (int i = 0; i < 24; i++)\r
107     {\r
108       newColors[i] = new Color(60, 160, 115);\r
109     }\r
110 \r
111     jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(\r
112         newColors);\r
113     String searchString = textfield.getText();\r
114 \r
115     searchGroup = new SuperGroup(searchString, ucs, true, true, false);\r
116 \r
117     for (int i = 0; i < searchResults.size(); i += 3)\r
118     {\r
119       // its possible edits may have occurred since search was performed\r
120       // account for this here\r
121       SequenceI seq = av.alignment.getSequenceAt(Integer.parseInt(\r
122           searchResults.elementAt(i).toString()));\r
123       int startRes = seq.findIndex(Integer.parseInt(\r
124           searchResults.elementAt(i + 1).toString())) - 1;\r
125       int endRes = seq.findIndex(Integer.parseInt(\r
126           searchResults.elementAt(i + 2).toString())) - 1;\r
127 \r
128       SequenceGroup sg = new SequenceGroup(searchString, ucs, true, true,\r
129                                            false, startRes, endRes);\r
130       sg.addSequence(seq);\r
131       av.alignment.addGroup(sg);\r
132       searchGroup.addGroup(sg);\r
133     }\r
134 \r
135     ap.av.alignment.addSuperGroup(searchGroup);\r
136     ap.highlightSearchResults(null);\r
137   }\r
138 \r
139   void doSearch(boolean findAll)\r
140   {\r
141     createNewGroup.setEnabled(false);\r
142 \r
143     String searchString = textfield.getText().toUpperCase();\r
144 \r
145     com.stevesoft.pat.Regex regex = new com.stevesoft.pat.Regex(searchString);\r
146 \r
147     searchResults = new Vector();\r
148 \r
149     int[] allResults = null;\r
150 \r
151     Sequence seq;\r
152     String item = null;\r
153     boolean found = false;\r
154 \r
155     ////// is the searchString a residue number?\r
156     try\r
157     {\r
158       int res = Integer.parseInt(searchString);\r
159       found = true;\r
160 \r
161       if (av.getSelectionGroup().getSize() > 0)\r
162       {\r
163         seq = (Sequence) (av.getSelectionGroup().getSequenceAt(0));\r
164       }\r
165       else\r
166       {\r
167         seq = (Sequence) av.getAlignment().getSequenceAt(0);\r
168       }\r
169 \r
170       searchResults.add(Integer.toString(av.getAlignment().findIndex(seq)));\r
171       searchResults.add(Integer.toString(seq.findIndex(res) - 1));\r
172       searchResults.add(Integer.toString(seq.findIndex(res) - 1));\r
173     }\r
174     catch (NumberFormatException ex)\r
175     {\r
176     }\r
177 \r
178     ///////////////////////////////////////////////\r
179     Color[] newColors = new Color[24];\r
180 \r
181     for (int i = 0; i < 24; i++)\r
182     {\r
183       newColors[i] = new Color(60, 160, 115);\r
184     }\r
185 \r
186     jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(\r
187         newColors);\r
188 \r
189     searchGroup = new SuperGroup(searchString, ucs, true, true, false);\r
190 \r
191     int end = av.alignment.getHeight();\r
192 \r
193     SequenceGroup selection = av.getSelectionGroup();\r
194 \r
195     if (selection != null)\r
196     {\r
197       if ( (selection.getSize() < 1) ||\r
198           ( (selection.getEndRes() - selection.getStartRes()) < 2))\r
199       {\r
200         selection = null;\r
201       }\r
202     }\r
203 \r
204     while (!found && (seqIndex < end))\r
205     {\r
206       seq = (Sequence) av.alignment.getSequenceAt(seqIndex);\r
207 \r
208       if ( (selection != null) && !selection.sequences.contains(seq))\r
209       {\r
210         seqIndex++;\r
211         resIndex = 0;\r
212 \r
213         continue;\r
214       }\r
215 \r
216       item = seq.getSequence().toUpperCase();\r
217 \r
218       if ( (selection != null) &&\r
219           (selection.getEndRes() < av.alignment.getWidth()))\r
220       {\r
221         item = item.substring(0, selection.getEndRes() + 1);\r
222       }\r
223 \r
224       ///Shall we ignore gaps????\r
225       StringBuffer noGaps = new StringBuffer();\r
226       int insertCount = 0;\r
227       Vector spaces = new Vector();\r
228 \r
229       for (int j = 0; j < item.length(); j++)\r
230       {\r
231         if (!jalview.util.Comparison.isGap(item.charAt(j)))\r
232         {\r
233           noGaps.append(item.charAt(j));\r
234           spaces.add(new Integer(insertCount));\r
235         }\r
236         else\r
237         {\r
238           insertCount++;\r
239         }\r
240       }\r
241 \r
242       for (int r = resIndex; r < noGaps.length(); r++)\r
243       {\r
244         if (regex.searchFrom(noGaps.toString(), r))\r
245         {\r
246           resIndex = regex.matchedFrom();\r
247 \r
248           if ( (selection != null) &&\r
249               ( (resIndex +\r
250                  Integer.parseInt(spaces.get(resIndex).toString())) <\r
251                selection.getStartRes()))\r
252           {\r
253             continue;\r
254           }\r
255 \r
256           searchResults.add(Integer.toString(seqIndex));\r
257 \r
258           int sres = seq.findPosition(resIndex +\r
259                                       Integer.parseInt(spaces.elementAt(\r
260               resIndex)\r
261               .toString()));\r
262           int eres = seq.findPosition(regex.matchedTo() - 1 +\r
263                                       Integer.parseInt(spaces.elementAt(regex.\r
264               matchedTo() -\r
265               1).toString()));\r
266 \r
267           searchResults.addElement(sres + "");\r
268           searchResults.addElement(eres + "");\r
269 \r
270           if (!findAll)\r
271           {\r
272             // thats enough, break and display the result\r
273             found = true;\r
274             resIndex++;\r
275 \r
276             break;\r
277           }\r
278 \r
279           r = resIndex;\r
280         }\r
281       }\r
282 \r
283       if (!found)\r
284       {\r
285         seqIndex++;\r
286         resIndex = 0;\r
287       }\r
288     }\r
289 \r
290     Vector idMatch = new Vector();\r
291 \r
292     for (int id = 0; id < av.alignment.getHeight(); id++)\r
293     {\r
294       if (regex.search(av.alignment.getSequenceAt(id).getName()))\r
295       {\r
296         idMatch.add(av.alignment.getSequenceAt(id));\r
297       }\r
298     }\r
299 \r
300     if ( (searchResults.size() == 0) && (idMatch.size() > 0))\r
301     {\r
302       ap.idPanel.highlightSearchResults(idMatch);\r
303     }\r
304 \r
305     if (searchResults.size() > 0)\r
306     {\r
307       allResults = new int[searchResults.size()];\r
308 \r
309       for (int i = 0; i < searchResults.size(); i++)\r
310       {\r
311         allResults[i] = Integer.parseInt(searchResults.get(i).toString());\r
312       }\r
313 \r
314       createNewGroup.setEnabled(true);\r
315     }\r
316     else\r
317     {\r
318       JOptionPane.showInternalMessageDialog(this, "Finished searching",\r
319                                             null,\r
320                                             JOptionPane.INFORMATION_MESSAGE);\r
321       resIndex = 0;\r
322       seqIndex = 0;\r
323     }\r
324 \r
325     // if allResults is null, this effectively switches displaySearch flag in seqCanvas\r
326     ap.highlightSearchResults(allResults);\r
327 \r
328     if (findAll)\r
329     {\r
330       String message = (searchResults.size() / 3) + " matches found.";\r
331       JOptionPane.showInternalMessageDialog(this, message, null,\r
332                                             JOptionPane.INFORMATION_MESSAGE);\r
333     }\r
334   }\r
335 }\r