find incrementally searches ID then subsequence matches. Dialog reports number of...
[jalview.git] / src / jalview / gui / Finder.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3  * Copyright (C) 2009 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 java.util.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25 import javax.swing.*;
26
27 import jalview.datamodel.*;
28 import jalview.jbgui.*;
29
30 /**
31  * DOCUMENT ME!
32  * 
33  * @author $author$
34  * @version $Revision$
35  */
36 public class Finder extends GFinder
37 {
38   AlignViewport av;
39
40   AlignmentPanel ap;
41
42   JInternalFrame frame;
43
44   int seqIndex = 0;
45
46   int resIndex = -1;
47
48   SearchResults searchResults;
49
50   /**
51    * Creates a new Finder object.
52    * 
53    * @param av
54    *                DOCUMENT ME!
55    * @param ap
56    *                DOCUMENT ME!
57    * @param f
58    *                DOCUMENT ME!
59    */
60   public Finder()
61   {
62     frame = new JInternalFrame();
63     frame.setContentPane(this);
64     frame.setLayer(JLayeredPane.PALETTE_LAYER);
65     Desktop.addInternalFrame(frame, "Find", 340, 110);
66
67     textfield.requestFocus();
68   }
69
70   /**
71    * DOCUMENT ME!
72    * 
73    * @param e
74    *                DOCUMENT ME!
75    */
76   public void findNext_actionPerformed(ActionEvent e)
77   {
78     if (getFocusedViewport())
79     {
80       doSearch(false);
81     }
82   }
83
84   /**
85    * DOCUMENT ME!
86    * 
87    * @param e
88    *                DOCUMENT ME!
89    */
90   public void findAll_actionPerformed(ActionEvent e)
91   {
92     if (getFocusedViewport())
93     {
94       resIndex = -1;
95       seqIndex = 0;
96       doSearch(true);
97     }
98   }
99
100   /**
101    * gets the topmost alignment window and sets av and ap accordingly
102    * @return false if no alignment window was found
103    */
104   boolean getFocusedViewport()
105   {
106     // now checks further down the window stack to fix bug https://mantis.lifesci.dundee.ac.uk/view.php?id=36008
107     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
108     for (int f=0;f<frames.length; f++) {
109       JInternalFrame frame = frames[f];
110       if (frame != null && frame instanceof AlignFrame)
111       {
112         av = ((AlignFrame) frame).viewport;
113         ap = ((AlignFrame) frame).alignPanel;
114         return true;
115       }
116     }
117     return false;
118   }
119
120   /**
121    * DOCUMENT ME!
122    * 
123    * @param e
124    *                DOCUMENT ME!
125    */
126   public void createNewGroup_actionPerformed(ActionEvent e)
127   {
128     SequenceI[] seqs = new SequenceI[searchResults.getSize()];
129     SequenceFeature[] features = new SequenceFeature[searchResults
130             .getSize()];
131
132     for (int i = 0; i < searchResults.getSize(); i++)
133     {
134       seqs[i] = searchResults.getResultSequence(i).getDatasetSequence();
135
136       features[i] = new SequenceFeature(textfield.getText().trim(),
137               "Search Results", null, searchResults.getResultStart(i),
138               searchResults.getResultEnd(i), "Search Results");
139     }
140
141     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
142             features, true, ap))
143     {
144       ap.alignFrame.showSeqFeatures.setSelected(true);
145       av.setShowSequenceFeatures(true);
146       ap.highlightSearchResults(null);
147     }
148   }
149
150   /**
151    * incrementally search the alignment
152    * 
153    * @param findAll
154    *                true means find all results and raise a dialog box
155    */
156   void doSearch(boolean findAll)
157   {
158     createNewGroup.setEnabled(false);
159
160     String searchString = textfield.getText().trim();
161
162     if (searchString.length() < 1)
163     {
164       return;
165     }
166     // TODO: extend finder to match descriptions, features and annotation, and
167     // other stuff
168     // TODO: add switches to control what is searched - sequences, IDS,
169     // descriptions, features
170     jalview.analysis.Finder finder = new jalview.analysis.Finder(
171             av.alignment, av.getSelectionGroup(), seqIndex, resIndex);
172     finder.setCaseSensitive(caseSensitive.isSelected());
173     finder.setFindAll(findAll);
174
175     finder.find(searchString); // returns true if anything was actually found
176
177     seqIndex = finder.getSeqIndex();
178     resIndex = finder.getResIndex();
179
180     searchResults = finder.getSearchResults(); // find(regex,
181                                                 // caseSensitive.isSelected(), )
182     Vector idMatch = finder.getIdMatch();
183     boolean haveResults=false;
184     // set or reset the GUI
185     if ((idMatch.size() > 0))
186     {
187       haveResults=true;
188       ap.idPanel.highlightSearchResults(idMatch);
189     } else {
190       ap.idPanel.highlightSearchResults(null);
191     }
192     
193     if (searchResults.getSize() > 0)
194     {
195       haveResults=true;
196       createNewGroup.setEnabled(true);
197     }
198     else
199     {
200       searchResults = null;
201     }
202
203     // if allResults is null, this effectively switches displaySearch flag in
204     // seqCanvas
205     ap.highlightSearchResults(searchResults);
206     // TODO: add enablers for 'SelectSequences' or 'SelectColumns' or
207     // 'SelectRegion' selection
208     if (!haveResults)
209     {
210       JOptionPane.showInternalMessageDialog(this, "Finished searching",
211               null, JOptionPane.INFORMATION_MESSAGE);
212       resIndex = -1;
213       seqIndex = 0;
214     }
215
216     if (findAll)
217     {
218       String message = (idMatch.size()>0) ? ""+idMatch.size()+" IDs" : "";
219       if (idMatch.size()>0 && searchResults.getSize()>0) {
220         message += " and ";
221       }
222       message += searchResults.getSize() + " subsequence matches found.";
223       JOptionPane.showInternalMessageDialog(this, message, null,
224               JOptionPane.INFORMATION_MESSAGE);
225       resIndex = -1;
226       seqIndex = 0;
227     }
228
229   }
230 }