New implementation for holding search results
[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 jalview.datamodel.*;\r
22 \r
23 import jalview.jbgui.*;\r
24 \r
25 import java.awt.*;\r
26 import java.awt.event.*;\r
27 \r
28 import java.util.*;\r
29 \r
30 import javax.swing.*;\r
31 import javax.swing.event.*;\r
32 \r
33 \r
34 /**\r
35  * DOCUMENT ME!\r
36  *\r
37  * @author $author$\r
38  * @version $Revision$\r
39  */\r
40 public class Finder extends GFinder\r
41 {\r
42     AlignViewport av;\r
43     AlignmentPanel ap;\r
44     JInternalFrame frame;\r
45     SuperGroup searchGroup;\r
46     int seqIndex = 0;\r
47     int resIndex = 0;\r
48 \r
49     SearchResults searchResults;\r
50 \r
51     /**\r
52      * Creates a new Finder object.\r
53      *\r
54      * @param av DOCUMENT ME!\r
55      * @param ap DOCUMENT ME!\r
56      * @param f DOCUMENT ME!\r
57      */\r
58     public Finder(AlignViewport av, AlignmentPanel ap, JInternalFrame f)\r
59     {\r
60         this.av = av;\r
61         this.ap = ap;\r
62         frame = f;\r
63 \r
64         // all a big pain, but we need to wait until the frame is visible before the textfield can\r
65         // obtain the focus/////////////////////////\r
66         frame.addInternalFrameListener(new InternalFrameAdapter()\r
67             {\r
68                 public void internalFrameOpened(InternalFrameEvent evt)\r
69                 {\r
70                     SwingUtilities.invokeLater(new Runnable()\r
71                         {\r
72                             public void run()\r
73                             {\r
74                                 textfield.requestFocus();\r
75                             }\r
76                         });\r
77                 }\r
78             });\r
79     }\r
80 \r
81 \r
82     /**\r
83      * DOCUMENT ME!\r
84      *\r
85      * @param e DOCUMENT ME!\r
86      */\r
87     public void findNext_actionPerformed(ActionEvent e)\r
88     {\r
89         doSearch(false);\r
90     }\r
91 \r
92     /**\r
93      * DOCUMENT ME!\r
94      *\r
95      * @param e DOCUMENT ME!\r
96      */\r
97     public void findAll_actionPerformed(ActionEvent e)\r
98     {\r
99         resIndex = 0;\r
100         seqIndex = 0;\r
101         doSearch(true);\r
102     }\r
103 \r
104 \r
105     /**\r
106      * DOCUMENT ME!\r
107      *\r
108      * @param e DOCUMENT ME!\r
109      */\r
110     public void createNewGroup_actionPerformed(ActionEvent e)\r
111     {\r
112         Color[] newColors = new Color[24];\r
113 \r
114         for (int i = 0; i < 24; i++)\r
115         {\r
116             newColors[i] = new Color(60, 160, 115);\r
117         }\r
118 \r
119         jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(newColors);\r
120         String searchString = textfield.getText();\r
121 \r
122         searchGroup = new SuperGroup(searchString, ucs, true, true, false);\r
123 \r
124         for (int i = 0; i < searchResults.getSize(); i ++ )\r
125         {\r
126             // its possible edits may have occurred since search was performed\r
127             // account for this here\r
128             SequenceI seq = searchResults.getResultSequence(i);\r
129             int startRes = seq.findIndex(searchResults.getResultStart(i)) - 1;\r
130             int endRes = seq.findIndex(searchResults.getResultEnd(i)) - 1;\r
131 \r
132             SequenceGroup sg = new SequenceGroup(searchString, ucs, true, true,\r
133                     false, startRes, endRes);\r
134             sg.addSequence(seq, false);\r
135             av.alignment.addGroup(sg);\r
136             searchGroup.addGroup(sg);\r
137         }\r
138 \r
139         ap.av.alignment.addSuperGroup(searchGroup);\r
140         ap.highlightSearchResults(null);\r
141     }\r
142 \r
143     /**\r
144      * DOCUMENT ME!\r
145      *\r
146      * @param findAll DOCUMENT ME!\r
147      */\r
148     void doSearch(boolean findAll)\r
149     {\r
150         createNewGroup.setEnabled(false);\r
151 \r
152         String searchString = textfield.getText().toUpperCase().trim();\r
153         if(searchString.length()<1)\r
154           return;\r
155 \r
156         com.stevesoft.pat.Regex regex = new com.stevesoft.pat.Regex(searchString);\r
157 \r
158         searchResults = new SearchResults();\r
159 \r
160         Sequence seq;\r
161         String item = null;\r
162         boolean found = false;\r
163 \r
164         ////// is the searchString a residue number?\r
165         try\r
166         {\r
167             int res = Integer.parseInt(searchString);\r
168             found = true;\r
169             if (av.getSelectionGroup() == null || av.getSelectionGroup().getSize() < 1)\r
170             {\r
171               seq = (Sequence) av.getAlignment().getSequenceAt(0);\r
172             }\r
173             else\r
174             {\r
175               seq = (Sequence) (av.getSelectionGroup().getSequenceAt(0));\r
176             }\r
177 \r
178             searchResults.addResult(seq, res, res);\r
179         }\r
180         catch (NumberFormatException ex)\r
181         {\r
182         }\r
183 \r
184         ///////////////////////////////////////////////\r
185         Color[] newColors = new Color[24];\r
186 \r
187         for (int i = 0; i < 24; i++)\r
188         {\r
189             newColors[i] = new Color(60, 160, 115);\r
190         }\r
191 \r
192         jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(newColors);\r
193 \r
194         searchGroup = new SuperGroup(searchString, ucs, true, true, false);\r
195 \r
196         int end = av.alignment.getHeight();\r
197 \r
198         SequenceGroup selection = av.getSelectionGroup();\r
199 \r
200         if (selection != null)\r
201         {\r
202             if ((selection.getSize() < 1) ||\r
203                     ((selection.getEndRes() - selection.getStartRes()) < 2))\r
204             {\r
205                 selection = null;\r
206             }\r
207         }\r
208 \r
209         while (!found && (seqIndex < end))\r
210         {\r
211             seq = (Sequence) av.alignment.getSequenceAt(seqIndex);\r
212 \r
213             if ((selection != null) && !selection.sequences.contains(seq))\r
214             {\r
215                 seqIndex++;\r
216                 resIndex = 0;\r
217 \r
218                 continue;\r
219             }\r
220 \r
221             item = seq.getSequence().toUpperCase();\r
222 \r
223             if ((selection != null) &&\r
224                     (selection.getEndRes() < av.alignment.getWidth()-1))\r
225             {\r
226                 item = item.substring(0, selection.getEndRes() + 1);\r
227             }\r
228 \r
229             ///Shall we ignore gaps????\r
230             StringBuffer noGapsSB = new StringBuffer();\r
231             int insertCount = 0;\r
232             Vector spaces = new Vector();\r
233 \r
234             for (int j = 0; j < item.length(); j++)\r
235             {\r
236                 if (!jalview.util.Comparison.isGap(item.charAt(j)))\r
237                 {\r
238                     noGapsSB.append(item.charAt(j));\r
239                     spaces.add(new Integer(insertCount));\r
240                 }\r
241                 else\r
242                 {\r
243                     insertCount++;\r
244                 }\r
245             }\r
246 \r
247             String noGaps = noGapsSB.toString();\r
248 \r
249             for (int r = resIndex; r < noGaps.length(); r++)\r
250             {\r
251 \r
252                 if (regex.searchFrom(noGaps, r))\r
253                 {\r
254                     resIndex = regex.matchedFrom();\r
255 \r
256                     if ((selection != null) &&\r
257                             ((resIndex +\r
258                             Integer.parseInt(spaces.get(resIndex).toString())) < selection.getStartRes()))\r
259                     {\r
260                         continue;\r
261                     }\r
262 \r
263 \r
264                     int sres = seq.findPosition(resIndex +\r
265                             Integer.parseInt(spaces.elementAt(resIndex)\r
266                                                    .toString()));\r
267                     int eres = seq.findPosition(regex.matchedTo() - 1 +\r
268                             Integer.parseInt(spaces.elementAt(regex.matchedTo() -\r
269                                     1).toString()));\r
270 \r
271                     searchResults.addResult(seq, sres, eres);\r
272 \r
273                     if (!findAll)\r
274                     {\r
275                         // thats enough, break and display the result\r
276                         found = true;\r
277                         resIndex++;\r
278 \r
279                         break;\r
280                     }\r
281 \r
282                     r = resIndex;\r
283                 }\r
284                 else\r
285                 {\r
286                   break;\r
287                 }\r
288             }\r
289 \r
290             if (!found)\r
291             {\r
292                 seqIndex++;\r
293                 resIndex = 0;\r
294             }\r
295         }\r
296 \r
297         Vector idMatch = new Vector();\r
298 \r
299         for (int id = 0; id < av.alignment.getHeight(); id++)\r
300         {\r
301             if (regex.search(av.alignment.getSequenceAt(id).getName()))\r
302             {\r
303                 idMatch.add(av.alignment.getSequenceAt(id));\r
304             }\r
305         }\r
306 \r
307         if ((searchResults.getSize() == 0) && (idMatch.size() > 0))\r
308         {\r
309             ap.idPanel.highlightSearchResults(idMatch);\r
310         }\r
311 \r
312 \r
313         int resultSize = searchResults.getSize();\r
314 \r
315         if (searchResults.getSize() > 0)\r
316           createNewGroup.setEnabled(true);\r
317         else\r
318           searchResults = null;\r
319 \r
320         // if allResults is null, this effectively switches displaySearch flag in seqCanvas\r
321         ap.highlightSearchResults(searchResults);\r
322 \r
323         if(!findAll && resultSize==0)\r
324         {\r
325             JOptionPane.showInternalMessageDialog(this, "Finished searching",\r
326                 null, JOptionPane.INFORMATION_MESSAGE);\r
327             resIndex = 0;\r
328             seqIndex = 0;\r
329         }\r
330 \r
331         if (findAll)\r
332         {\r
333           String message = resultSize + " matches found.";\r
334           JOptionPane.showInternalMessageDialog(this, message, null,\r
335                                                 JOptionPane.INFORMATION_MESSAGE);\r
336         }\r
337 \r
338     }\r
339 }\r