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