Ignores gaps when searching
[jalview.git] / src / jalview / gui / Finder.java
1 package jalview.gui;\r
2 \r
3 import jalview.jbgui.GFinder;\r
4 import jalview.datamodel.*;\r
5 import java.awt.event.*;\r
6 import javax.swing.*;\r
7 import javax.swing.event.*;\r
8 import java.util.*;\r
9 import java.util.regex.*;\r
10 \r
11 public class Finder extends GFinder\r
12 {\r
13   AlignViewport av;\r
14   AlignmentPanel ap;\r
15   JInternalFrame frame;\r
16   String searchString;\r
17 \r
18   int seqIndex = 0;\r
19   int resIndex = 0;\r
20   public Finder(AlignViewport av, AlignmentPanel ap, JInternalFrame f)\r
21   {\r
22     this.av = av;\r
23     this.ap = ap;\r
24     frame = f;\r
25 \r
26     // all a big pain, but we need to wait until the frame is visible before the textfield can\r
27     // obtain the focus/////////////////////////\r
28     frame.addInternalFrameListener(new InternalFrameAdapter()\r
29     {\r
30       public void internalFrameOpened(InternalFrameEvent evt)\r
31       {\r
32         SwingUtilities.invokeLater(new Runnable()\r
33         {\r
34           public void run()\r
35           {\r
36             textfield.requestFocus();\r
37           }\r
38        });\r
39    }\r
40 });\r
41 \r
42   }\r
43 \r
44   public void textfield_actionPerformed(ActionEvent e)\r
45   {\r
46     doSearch(false);\r
47   }\r
48 \r
49   public void findNext_actionPerformed(ActionEvent e)\r
50   {\r
51     doSearch(false);\r
52   }\r
53 \r
54   public void findAll_actionPerformed(ActionEvent e)\r
55   {\r
56     resIndex=0;\r
57     seqIndex=0;\r
58     doSearch(true);\r
59   }\r
60 \r
61   public void cancel_actionPerformed(ActionEvent e)\r
62   {\r
63     try{\r
64       // if allResults is null, this effectively switches displaySearch flag in seqCanvas\r
65       ap.highlightSearchResults( null );\r
66       frame.setClosed(true);\r
67     }catch(Exception ex){ }\r
68 \r
69   }\r
70 \r
71   void doSearch(boolean findAll)\r
72   {\r
73     searchString = textfield.getText().toUpperCase();\r
74 \r
75     ArrayList searchResults = new ArrayList();\r
76     int [] allResults = null;\r
77 \r
78     Sequence seq;\r
79     String item;\r
80     boolean found = false;\r
81 \r
82     /// is the searchString a residue number?\r
83     try{\r
84       int res = Integer.parseInt(searchString);\r
85       found = true;\r
86 \r
87       if(av.getSelection().size()>0)\r
88         seq = (Sequence)(av.getSelection().sequenceAt(0));\r
89       else\r
90         seq = (Sequence)av.getAlignment().getSequenceAt(0);\r
91 \r
92       searchResults.add( Integer.toString( av.getAlignment().findIndex(seq) ) );\r
93       searchResults.add( Integer.toString( seq.findIndex(res)-1 ) );\r
94       searchResults.add( Integer.toString( seq.findIndex(res)-1 ) );\r
95 \r
96 \r
97       //av.getAlignment().getSequenceAt(seq).findPosition(res)\r
98     }catch(NumberFormatException ex){}\r
99 \r
100 \r
101     while( !found && seqIndex<av.getAlignment().getHeight())\r
102     {\r
103       seq = (Sequence)av.getAlignment().getSequenceAt(seqIndex);\r
104       if(av.getSelection().size()>0 && !av.getSelection().contains(seq))\r
105       {\r
106         // if a selection has been made, only search within that selection\r
107         seqIndex++;\r
108         resIndex=0;\r
109         continue;\r
110       }\r
111 \r
112       item = seq.getSequence();\r
113 \r
114       ///Shall we ignore gaps????\r
115       StringBuffer noGaps = new StringBuffer();\r
116       int insertCount=0;\r
117       ArrayList spaces = new ArrayList();\r
118 \r
119       for (int j=0; j < item.length(); j++)\r
120       {\r
121 \r
122         if(!jalview.util.Comparison.isGap(item.charAt(j)))\r
123          {\r
124            noGaps.append(item.charAt(j));\r
125            spaces.add(new Integer(insertCount));\r
126          }\r
127         else\r
128            insertCount++;\r
129       }\r
130 \r
131 \r
132       Pattern pattern = Pattern.compile(searchString);\r
133       Matcher matcher = pattern.matcher(noGaps);\r
134 \r
135       for(int r = resIndex; r<noGaps.length(); r++)\r
136       {\r
137 \r
138        if( matcher.find( r ) )\r
139        {\r
140          resIndex = matcher.start();\r
141 \r
142          searchResults.add( Integer.toString( seqIndex) );\r
143          searchResults.add( Integer.toString( resIndex+ Integer.parseInt(spaces.get(resIndex).toString()) ) );\r
144          searchResults.add( Integer.toString( matcher.end()-1 + Integer.parseInt(spaces.get(matcher.end()-1).toString()) ) );\r
145          if(!findAll)\r
146          {\r
147            // thats enough, break and display the result\r
148            found = true;\r
149            resIndex++;\r
150            break;\r
151          }\r
152 \r
153          r=resIndex+1;\r
154        }\r
155       }\r
156       if(!found)\r
157       {\r
158         seqIndex++;\r
159         resIndex = 0;\r
160       }\r
161     }\r
162 \r
163     if(searchResults.size()>0)\r
164     {\r
165       allResults = new int[searchResults.size()];\r
166       for(int i=0; i<searchResults.size(); i++)\r
167         allResults[i] = Integer.parseInt(searchResults.get(i).toString());\r
168 \r
169     }\r
170     else\r
171     {\r
172       JOptionPane.showInternalMessageDialog(this, "Finished searching", null, JOptionPane.INFORMATION_MESSAGE);\r
173       resIndex=0;\r
174       seqIndex=0;\r
175     }\r
176 \r
177     // if allResults is null, this effectively switches displaySearch flag in seqCanvas\r
178     ap.highlightSearchResults( allResults );\r
179 \r
180     if (findAll)\r
181     {\r
182       String message =  (searchResults.size()/3) + " matches found.";\r
183       JOptionPane.showInternalMessageDialog(this, message, null,\r
184                                             JOptionPane.INFORMATION_MESSAGE);\r
185     }\r
186 \r
187   }\r
188 \r
189 }\r