partial patch for * JAL-466
[jalview.git] / src / jalview / gui / Finder.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3  * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.gui;
19
20 import java.util.*;
21
22 import java.awt.*;
23 import java.awt.event.*;
24 import javax.swing.*;
25
26 import jalview.datamodel.*;
27 import jalview.jbgui.*;
28
29 /**
30  * DOCUMENT ME!
31  * 
32  * @author $author$
33  * @version $Revision$
34  */
35 public class Finder extends GFinder
36 {
37   AlignViewport av;
38
39   AlignmentPanel ap;
40
41   JInternalFrame frame;
42
43   int seqIndex = 0;
44
45   int resIndex = -1;
46
47   SearchResults searchResults;
48
49   /**
50    * Creates a new Finder object.
51    * 
52    * @param av
53    *          DOCUMENT ME!
54    * @param ap
55    *          DOCUMENT ME!
56    * @param f
57    *          DOCUMENT ME!
58    */
59   public Finder()
60   {
61     this(null,null);
62     focusfixed=false;
63   }
64   public Finder(AlignViewport viewport, AlignmentPanel alignPanel)
65   {
66     av = viewport;
67     ap = alignPanel; 
68     focusfixed=true;
69     frame = new JInternalFrame();
70     frame.setContentPane(this);
71     frame.setLayer(JLayeredPane.PALETTE_LAYER);
72     Desktop.addInternalFrame(frame, "Find", 340, 110);
73
74     textfield.requestFocus();
75   }
76
77   /**
78    * DOCUMENT ME!
79    * 
80    * @param e
81    *          DOCUMENT ME!
82    */
83   public void findNext_actionPerformed(ActionEvent e)
84   {
85     if (getFocusedViewport())
86     {
87       doSearch(false);
88     }
89   }
90
91   /**
92    * DOCUMENT ME!
93    * 
94    * @param e
95    *          DOCUMENT ME!
96    */
97   public void findAll_actionPerformed(ActionEvent e)
98   {
99     if (getFocusedViewport())
100     {
101       resIndex = -1;
102       seqIndex = 0;
103       doSearch(true);
104     }
105   }
106   /**
107    * do we only search a given alignment view ?
108    */
109   private boolean focusfixed;
110
111   /**
112    * if !focusfixed and not in a desktop environment, checks that av and ap are
113    * valid. Otherwise, gets the topmost alignment window and sets av and ap
114    * accordingly
115    * 
116    * @return false if no alignment window was found
117    */
118   boolean getFocusedViewport()
119   {
120     if (focusfixed || Desktop.desktop==null)
121     {
122       if (ap!=null && av!=null)
123       {
124         return true;
125       }
126       // we aren't in a desktop environment, so give up now.
127       return false;
128     }
129     // now checks further down the window stack to fix bug
130     // https://mantis.lifesci.dundee.ac.uk/view.php?id=36008
131     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
132     for (int f = 0; f < frames.length; f++)
133     {
134       JInternalFrame frame = frames[f];
135       if (frame != null && frame instanceof AlignFrame)
136       {
137         av = ((AlignFrame) frame).viewport;
138         ap = ((AlignFrame) frame).alignPanel;
139         return true;
140       }
141     }
142     return false;
143   }
144
145   /**
146    * DOCUMENT ME!
147    * 
148    * @param e
149    *          DOCUMENT ME!
150    */
151   public void createNewGroup_actionPerformed(ActionEvent e)
152   {
153     SequenceI[] seqs = new SequenceI[searchResults.getSize()];
154     SequenceFeature[] features = new SequenceFeature[searchResults
155             .getSize()];
156
157     for (int i = 0; i < searchResults.getSize(); i++)
158     {
159       seqs[i] = searchResults.getResultSequence(i).getDatasetSequence();
160
161       features[i] = new SequenceFeature(textfield.getText().trim(),
162               "Search Results", null, searchResults.getResultStart(i),
163               searchResults.getResultEnd(i), "Search Results");
164     }
165
166     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
167             features, true, ap))
168     {
169       ap.alignFrame.showSeqFeatures.setSelected(true);
170       av.setShowSequenceFeatures(true);
171       ap.highlightSearchResults(null);
172     }
173   }
174
175   /**
176    * incrementally search the alignment
177    * 
178    * @param findAll
179    *          true means find all results and raise a dialog box
180    */
181   void doSearch(boolean findAll)
182   {
183     createNewGroup.setEnabled(false);
184
185     String searchString = textfield.getText().trim();
186
187     if (searchString.length() < 1)
188     {
189       return;
190     }
191     // TODO: extend finder to match descriptions, features and annotation, and
192     // other stuff
193     // TODO: add switches to control what is searched - sequences, IDS,
194     // descriptions, features
195     jalview.analysis.Finder finder = new jalview.analysis.Finder(
196             av.alignment, av.getSelectionGroup(), seqIndex, resIndex);
197     finder.setCaseSensitive(caseSensitive.isSelected());
198     finder.setFindAll(findAll);
199
200     finder.find(searchString); // returns true if anything was actually found
201
202     seqIndex = finder.getSeqIndex();
203     resIndex = finder.getResIndex();
204
205     searchResults = finder.getSearchResults(); // find(regex,
206     // caseSensitive.isSelected(), )
207     Vector idMatch = finder.getIdMatch();
208     boolean haveResults = false;
209     // set or reset the GUI
210     if ((idMatch.size() > 0))
211     {
212       haveResults = true;
213       ap.idPanel.highlightSearchResults(idMatch);
214     }
215     else
216     {
217       ap.idPanel.highlightSearchResults(null);
218     }
219
220     if (searchResults.getSize() > 0)
221     {
222       haveResults = true;
223       createNewGroup.setEnabled(true);
224     }
225     else
226     {
227       searchResults = null;
228     }
229
230     // if allResults is null, this effectively switches displaySearch flag in
231     // seqCanvas
232     ap.highlightSearchResults(searchResults);
233     // TODO: add enablers for 'SelectSequences' or 'SelectColumns' or
234     // 'SelectRegion' selection
235     if (!haveResults)
236     {
237       JOptionPane.showInternalMessageDialog(this, "Finished searching",
238               null, JOptionPane.INFORMATION_MESSAGE);
239       resIndex = -1;
240       seqIndex = 0;
241     }
242
243     if (findAll)
244     {
245       String message = (idMatch.size() > 0) ? "" + idMatch.size() + " IDs"
246               : "";
247       if (idMatch.size() > 0 && searchResults.getSize() > 0)
248       {
249         message += " and ";
250       }
251       message += searchResults.getSize() + " subsequence matches found.";
252       JOptionPane.showInternalMessageDialog(this, message, null,
253               JOptionPane.INFORMATION_MESSAGE);
254       resIndex = -1;
255       seqIndex = 0;
256     }
257
258   }
259 }