5aed68843e1c8e00ebd70398620b07adc7c4d35d
[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    * checks that av and ap are valid, and if not,
113    * gets the topmost alignment window and sets av and ap accordingly
114    * 
115    * @return false if no alignment window was found
116    */
117   boolean getFocusedViewport()
118   {
119     if (focusfixed || Desktop.desktop==null)
120     {
121       if (ap!=null && av!=null)
122       {
123         return true;
124       }
125       // we aren't in a desktop environment, so give up now.
126       return false;
127     }
128     // now checks further down the window stack to fix bug
129     // https://mantis.lifesci.dundee.ac.uk/view.php?id=36008
130     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
131     for (int f = 0; f < frames.length; f++)
132     {
133       JInternalFrame frame = frames[f];
134       if (frame != null && frame instanceof AlignFrame)
135       {
136         av = ((AlignFrame) frame).viewport;
137         ap = ((AlignFrame) frame).alignPanel;
138         return true;
139       }
140     }
141     return false;
142   }
143
144   /**
145    * DOCUMENT ME!
146    * 
147    * @param e
148    *          DOCUMENT ME!
149    */
150   public void createNewGroup_actionPerformed(ActionEvent e)
151   {
152     SequenceI[] seqs = new SequenceI[searchResults.getSize()];
153     SequenceFeature[] features = new SequenceFeature[searchResults
154             .getSize()];
155
156     for (int i = 0; i < searchResults.getSize(); i++)
157     {
158       seqs[i] = searchResults.getResultSequence(i).getDatasetSequence();
159
160       features[i] = new SequenceFeature(textfield.getText().trim(),
161               "Search Results", null, searchResults.getResultStart(i),
162               searchResults.getResultEnd(i), "Search Results");
163     }
164
165     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
166             features, true, ap))
167     {
168       ap.alignFrame.showSeqFeatures.setSelected(true);
169       av.setShowSequenceFeatures(true);
170       ap.highlightSearchResults(null);
171     }
172   }
173
174   /**
175    * incrementally search the alignment
176    * 
177    * @param findAll
178    *          true means find all results and raise a dialog box
179    */
180   void doSearch(boolean findAll)
181   {
182     createNewGroup.setEnabled(false);
183
184     String searchString = textfield.getText().trim();
185
186     if (searchString.length() < 1)
187     {
188       return;
189     }
190     // TODO: extend finder to match descriptions, features and annotation, and
191     // other stuff
192     // TODO: add switches to control what is searched - sequences, IDS,
193     // descriptions, features
194     jalview.analysis.Finder finder = new jalview.analysis.Finder(
195             av.alignment, av.getSelectionGroup(), seqIndex, resIndex);
196     finder.setCaseSensitive(caseSensitive.isSelected());
197     finder.setFindAll(findAll);
198
199     finder.find(searchString); // returns true if anything was actually found
200
201     seqIndex = finder.getSeqIndex();
202     resIndex = finder.getResIndex();
203
204     searchResults = finder.getSearchResults(); // find(regex,
205     // caseSensitive.isSelected(), )
206     Vector idMatch = finder.getIdMatch();
207     boolean haveResults = false;
208     // set or reset the GUI
209     if ((idMatch.size() > 0))
210     {
211       haveResults = true;
212       ap.idPanel.highlightSearchResults(idMatch);
213     }
214     else
215     {
216       ap.idPanel.highlightSearchResults(null);
217     }
218
219     if (searchResults.getSize() > 0)
220     {
221       haveResults = true;
222       createNewGroup.setEnabled(true);
223     }
224     else
225     {
226       searchResults = null;
227     }
228
229     // if allResults is null, this effectively switches displaySearch flag in
230     // seqCanvas
231     ap.highlightSearchResults(searchResults);
232     // TODO: add enablers for 'SelectSequences' or 'SelectColumns' or
233     // 'SelectRegion' selection
234     if (!haveResults)
235     {
236       JOptionPane.showInternalMessageDialog(this, "Finished searching",
237               null, JOptionPane.INFORMATION_MESSAGE);
238       resIndex = -1;
239       seqIndex = 0;
240     }
241
242     if (findAll)
243     {
244       String message = (idMatch.size() > 0) ? "" + idMatch.size() + " IDs"
245               : "";
246       if (idMatch.size() > 0 && searchResults.getSize() > 0)
247       {
248         message += " and ";
249       }
250       message += searchResults.getSize() + " subsequence matches found.";
251       JOptionPane.showInternalMessageDialog(this, message, null,
252               JOptionPane.INFORMATION_MESSAGE);
253       resIndex = -1;
254       seqIndex = 0;
255     }
256
257   }
258 }