PageRenderTime 112ms CodeModel.GetById 96ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-0-pre3/org/gjt/sp/jedit/search/SearchBar.java

#
Java | 381 lines | 272 code | 33 blank | 76 comment | 36 complexity | 764c5e4831ff78ec106da590bbdd8ac3 MD5 | raw file
  1/*
  2 * SearchBar.java - Search & replace toolbar
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Portions copyright (C) 2000, 2001 Slava Pestov
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit.search;
 24
 25//{{{ Imports
 26import java.awt.event.*;
 27import java.awt.*;
 28import javax.swing.border.*;
 29import javax.swing.event.*;
 30import javax.swing.*;
 31import org.gjt.sp.jedit.*;
 32import org.gjt.sp.jedit.gui.HistoryTextField;
 33import org.gjt.sp.jedit.textarea.*;
 34import org.gjt.sp.util.Log;
 35//}}}
 36
 37public class SearchBar extends JPanel
 38{
 39	//{{{ SearchBar constructor
 40	public SearchBar(final View view)
 41	{
 42		super(new BorderLayout());
 43
 44		this.view = view;
 45
 46		JLabel label = new JLabel(jEdit.getProperty("view.search.find"));
 47		label.setBorder(new EmptyBorder(0,2,0,12));
 48		add(label,BorderLayout.WEST);
 49		Box box = new Box(BoxLayout.Y_AXIS);
 50		box.add(Box.createGlue());
 51		box.add(find = new HistoryTextField("find"));
 52		find.setSelectAllOnFocus(true);
 53		Dimension min = find.getPreferredSize();
 54		min.width = Integer.MAX_VALUE;
 55		find.setMaximumSize(min);
 56		ActionHandler actionHandler = new ActionHandler();
 57		find.addKeyListener(new KeyHandler());
 58		find.addActionListener(actionHandler);
 59		find.getDocument().addDocumentListener(new DocumentHandler());
 60		box.add(Box.createGlue());
 61		add(box,BorderLayout.CENTER);
 62
 63		Insets margin = new Insets(1,1,1,1);
 64
 65		Box buttons = new Box(BoxLayout.X_AXIS);
 66		buttons.add(Box.createHorizontalStrut(12));
 67		buttons.add(ignoreCase = new JCheckBox(jEdit.getProperty(
 68			"search.case")));
 69		ignoreCase.addActionListener(actionHandler);
 70		ignoreCase.setMargin(margin);
 71		buttons.add(Box.createHorizontalStrut(2));
 72		buttons.add(regexp = new JCheckBox(jEdit.getProperty(
 73			"search.regexp")));
 74		regexp.addActionListener(actionHandler);
 75		regexp.setMargin(margin);
 76		buttons.add(Box.createHorizontalStrut(2));
 77		buttons.add(hyperSearch = new JCheckBox(jEdit.getProperty(
 78			"search.hypersearch")));
 79		hyperSearch.addActionListener(actionHandler);
 80		hyperSearch.setMargin(margin);
 81
 82		update();
 83
 84		add(buttons,BorderLayout.EAST);
 85
 86		//{{{ Create the timer used by incremental search
 87		timer = new Timer(0,new ActionListener()
 88		{
 89			public void actionPerformed(ActionEvent evt)
 90			{
 91				if(!incrementalSearch(searchStart,searchReverse))
 92				{
 93					if(!incrementalSearch(
 94						(searchReverse
 95						? view.getBuffer().getLength()
 96						: 0),searchReverse))
 97					{
 98						// not found at all.
 99						view.getStatus().setMessageAndClear(
100							jEdit.getProperty(
101							"view.status.search-not-found"));
102					}
103				}
104			}
105		}); //}}}
106	} //}}}
107
108	//{{{ getField() method
109	public HistoryTextField getField()
110	{
111		return find;
112	} //}}}
113
114	//{{{ setHyperSearch() method
115	public void setHyperSearch(boolean hyperSearch)
116	{
117		jEdit.setBooleanProperty("view.search.hypersearch.toggle",hyperSearch);
118		this.hyperSearch.setSelected(hyperSearch);
119	} //}}}
120
121	//{{{ update() method
122	public void update()
123	{
124		ignoreCase.setSelected(SearchAndReplace.getIgnoreCase());
125		regexp.setSelected(SearchAndReplace.getRegexp());
126		hyperSearch.setSelected(jEdit.getBooleanProperty(
127			"view.search.hypersearch.toggle"));
128	} //}}}
129
130	//{{{ Private members
131
132	//{{{ Instance variables
133	private View view;
134	private HistoryTextField find;
135	private JCheckBox ignoreCase, regexp, hyperSearch;
136	private Timer timer;
137	private int searchStart;
138	private boolean searchReverse;
139	//}}}
140
141	//{{{ find() method
142	private void find(boolean reverse)
143	{
144		timer.stop();
145
146		String text = find.getText();
147		//{{{ If nothing entered, show search and replace dialog box
148		if(text.length() == 0)
149		{
150			jEdit.setBooleanProperty("search.hypersearch.toggle",
151				hyperSearch.isSelected());
152			new SearchDialog(view,null);
153		} //}}}
154		//{{{ HyperSearch
155		else if(hyperSearch.isSelected())
156		{
157			find.setText(null);
158			SearchAndReplace.setSearchString(text);
159			SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
160			SearchAndReplace.hyperSearch(view);
161		} //}}}
162		//{{{ Incremental search
163		else
164		{
165			// on enter, start search from end
166			// of current match to find next one
167			int start;
168			JEditTextArea textArea = view.getTextArea();
169			Selection s = textArea.getSelectionAtOffset(
170				textArea.getCaretPosition());
171			if(s == null)
172				start = textArea.getCaretPosition();
173			else if(reverse)
174				start = s.getStart();
175			else
176				start = s.getEnd();
177
178			if(!incrementalSearch(start,reverse))
179			{
180				// not found. start from
181				// beginning
182				if(!incrementalSearch(reverse
183					? view.getBuffer().getLength()
184					: 0,reverse))
185				{
186					// not found at all.
187					view.getStatus().setMessageAndClear(
188						jEdit.getProperty(
189						"view.status.search-not-found"));
190				}
191				else
192				{
193					// inform user search restarted
194					view.getStatus().setMessageAndClear(
195						jEdit.getProperty("view.status.auto-wrap"));
196					// beep if beep property set
197					if(jEdit.getBooleanProperty("search.beepOnSearchAutoWrap"))
198					{
199						getToolkit().beep();
200					}
201				}
202			}
203		} //}}}
204	} //}}}
205
206	//{{{ incrementalSearch() method
207	private boolean incrementalSearch(int start, boolean reverse)
208	{
209		/* For example, if the current fileset is a directory,
210		 * C+g will find the next match within that fileset.
211		 * This can be annoying if you have just done an
212		 * incremental search and want the next occurrence
213		 * in the current buffer. */
214		SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
215		SearchAndReplace.setSearchString(find.getText());
216		SearchAndReplace.setReverseSearch(reverse);
217
218		try
219		{
220			if(SearchAndReplace.find(view,view.getBuffer(),start))
221				return true;
222		}
223		catch(Exception e)
224		{
225			Log.log(Log.DEBUG,this,e);
226
227			// invalid regexp, ignore
228			// return true to avoid annoying beeping while
229			// typing a re
230			return true;
231		}
232
233		return false;
234	} //}}}
235
236	//{{{ timerIncrementalSearch() method
237	private void timerIncrementalSearch(int start, boolean reverse)
238	{
239		this.searchStart = start;
240		this.searchReverse = reverse;
241
242		timer.stop();
243		timer.setRepeats(false);
244		timer.setInitialDelay(150);
245		timer.start();
246	} //}}}
247
248	//}}}
249
250	//{{{ Inner classes
251
252	//{{{ ActionHandler class
253	class ActionHandler implements ActionListener
254	{
255		//{{{ actionPerformed() method
256		public void actionPerformed(ActionEvent evt)
257		{
258			Object source = evt.getSource();
259			if(evt.getSource() == find)
260				find(false);
261			else if(evt.getSource() == hyperSearch)
262			{
263				jEdit.setBooleanProperty("view.search.hypersearch.toggle",
264					hyperSearch.isSelected());
265				update();
266			}
267			else if(evt.getSource() == ignoreCase)
268			{
269				SearchAndReplace.setIgnoreCase(ignoreCase
270					.isSelected());
271			}
272			else if(evt.getSource() == regexp)
273			{
274				SearchAndReplace.setRegexp(regexp
275					.isSelected());
276			}
277		} //}}}
278	} //}}}
279
280	//{{{ DocumentHandler class
281	class DocumentHandler implements DocumentListener
282	{
283		//{{{ insertUpdate() method
284		public void insertUpdate(DocumentEvent evt)
285		{
286			// on insert, start search from beginning of
287			// current match. This will continue to highlight
288			// the current match until another match is found
289			if(!hyperSearch.isSelected())
290			{
291				int start;
292				JEditTextArea textArea = view.getTextArea();
293				Selection s = textArea.getSelectionAtOffset(
294					textArea.getCaretPosition());
295				if(s == null)
296					start = textArea.getCaretPosition();
297				else
298					start = s.getStart();
299
300				timerIncrementalSearch(start,false);
301			}
302		} //}}}
303
304		//{{{ removeUpdate() method
305		public void removeUpdate(DocumentEvent evt)
306		{
307			// on backspace, restart from beginning
308			if(!hyperSearch.isSelected())
309			{
310				String text = find.getText();
311				if(text.length() != 0)
312				{
313					// don't beep if not found.
314					// subsequent beeps are very
315					// annoying when backspacing an
316					// invalid search string.
317					if(regexp.isSelected())
318					{
319						// reverse regexp search
320						// not supported yet, so
321						// 'sumulate' with restart
322						timerIncrementalSearch(0,false);
323					}
324					else
325					{
326						int start;
327						JEditTextArea textArea = view.getTextArea();
328						Selection s = textArea.getSelectionAtOffset(
329							textArea.getCaretPosition());
330						if(s == null)
331							start = textArea.getCaretPosition();
332						else
333							start = s.getStart();
334						timerIncrementalSearch(start,true);
335					}
336				}
337			}
338		} //}}}
339
340		//{{{ changedUpdate() method
341		public void changedUpdate(DocumentEvent evt) {}
342		//}}}
343	} //}}}
344
345	//{{{ KeyHandler class
346	class KeyHandler extends KeyAdapter
347	{
348		//{{{ keyPressed() method
349		public void keyPressed(KeyEvent evt)
350		{
351			switch(evt.getKeyCode())
352			{
353			case KeyEvent.VK_LEFT:
354			case KeyEvent.VK_RIGHT:
355			case KeyEvent.VK_UP:
356			case KeyEvent.VK_DOWN:
357				if(!hyperSearch.isSelected())
358				{
359					evt.consume();
360					view.getEditPane().focusOnTextArea();
361					view.getEditPane().getTextArea()
362						.processKeyEvent(evt);
363				}
364				break;
365			case KeyEvent.VK_ESCAPE:
366				evt.consume();
367				view.getEditPane().focusOnTextArea();
368				break;
369			case KeyEvent.VK_ENTER:
370				if(evt.isShiftDown())
371				{
372					evt.consume();
373					find(true);
374				}
375				break;
376			}
377		} //}}}
378	} //}}}
379
380	//}}}
381}