PageRenderTime 320ms CodeModel.GetById 292ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/org/gjt/sp/jedit/search/SearchBar.java

#
Java | 426 lines | 303 code | 41 blank | 82 comment | 48 complexity | abd62aef947cd2a41503ff8ad3e9147d MD5 | raw file
  1/*
  2 * SearchBar.java - Search & replace toolbar
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2000, 2001, 2002 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.event.*;
 29import javax.swing.*;
 30import org.gjt.sp.jedit.*;
 31import org.gjt.sp.jedit.gui.*;
 32import org.gjt.sp.jedit.textarea.*;
 33import org.gjt.sp.util.Log;
 34//}}}
 35
 36/**
 37 * Incremental search tool bar.
 38 */
 39public class SearchBar extends JPanel
 40{
 41	//{{{ SearchBar constructor
 42	public SearchBar(final View view, boolean temp)
 43	{
 44		setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
 45
 46		this.view = view;
 47
 48		add(Box.createHorizontalStrut(2));
 49
 50		JLabel label = new JLabel(jEdit.getProperty("view.search.find"));
 51		add(label);
 52		add(Box.createHorizontalStrut(12));
 53		add(find = new HistoryTextField("find"));
 54		find.setSelectAllOnFocus(true);
 55		Dimension max = find.getPreferredSize();
 56		max.width = Integer.MAX_VALUE;
 57		find.setMaximumSize(max);
 58		ActionHandler actionHandler = new ActionHandler();
 59		find.addKeyListener(new KeyHandler());
 60		find.addActionListener(actionHandler);
 61		find.getDocument().addDocumentListener(new DocumentHandler());
 62
 63		Insets margin = new Insets(1,1,1,1);
 64
 65		add(Box.createHorizontalStrut(12));
 66		add(ignoreCase = new JCheckBox(jEdit.getProperty(
 67			"search.case")));
 68		ignoreCase.addActionListener(actionHandler);
 69		ignoreCase.setMargin(margin);
 70		ignoreCase.setRequestFocusEnabled(false);
 71		add(Box.createHorizontalStrut(2));
 72		add(regexp = new JCheckBox(jEdit.getProperty(
 73			"search.regexp")));
 74		regexp.addActionListener(actionHandler);
 75		regexp.setMargin(margin);
 76		regexp.setRequestFocusEnabled(false);
 77		add(Box.createHorizontalStrut(2));
 78		add(hyperSearch = new JCheckBox(jEdit.getProperty(
 79			"search.hypersearch")));
 80		hyperSearch.addActionListener(actionHandler);
 81		hyperSearch.setMargin(margin);
 82		hyperSearch.setRequestFocusEnabled(false);
 83
 84		update();
 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		// if 'temp' is true, hide search bar after user is done with it
108		this.temp = temp;
109
110		propertiesChanged();
111	} //}}}
112
113	//{{{ getField() method
114	public HistoryTextField getField()
115	{
116		return find;
117	} //}}}
118
119	//{{{ setHyperSearch() method
120	public void setHyperSearch(boolean hyperSearch)
121	{
122		jEdit.setBooleanProperty("view.search.hypersearch.toggle",hyperSearch);
123		this.hyperSearch.setSelected(hyperSearch);
124	} //}}}
125
126	//{{{ update() method
127	public void update()
128	{
129		ignoreCase.setSelected(SearchAndReplace.getIgnoreCase());
130		regexp.setSelected(SearchAndReplace.getRegexp());
131		hyperSearch.setSelected(jEdit.getBooleanProperty(
132			"view.search.hypersearch.toggle"));
133	} //}}}
134
135	//{{{ propertiesChanged() method
136	public void propertiesChanged()
137	{
138		if(temp)
139		{
140			if(close == null)
141			{
142				close = new RolloverButton(GUIUtilities.loadIcon("closebox.gif"));
143				close.addActionListener(new ActionHandler());
144				close.setToolTipText(jEdit.getProperty(
145					"view.search.close-tooltip"));
146			}
147			add(close);
148		}
149		else if(close != null)
150			remove(close);
151	} //}}}
152
153	//{{{ Private members
154
155	//{{{ Instance variables
156	private View view;
157	private HistoryTextField find;
158	private JCheckBox ignoreCase, regexp, hyperSearch;
159	private Timer timer;
160
161	// close button only there if 'temp' is true
162	private RolloverButton close;
163
164	private int searchStart;
165	private boolean searchReverse;
166	private boolean temp;
167	//}}}
168
169	//{{{ find() method
170	private void find(boolean reverse)
171	{
172		timer.stop();
173
174		String text = find.getText();
175		//{{{ If nothing entered, show search and replace dialog box
176		if(text.length() == 0)
177		{
178			jEdit.setBooleanProperty("search.hypersearch.toggle",
179				hyperSearch.isSelected());
180			SearchDialog.showSearchDialog(view,null,SearchDialog.CURRENT_BUFFER);
181		} //}}}
182		//{{{ HyperSearch
183		else if(hyperSearch.isSelected())
184		{
185			if(temp)
186			{
187				view.removeToolBar(SearchBar.this);
188			}
189                        else
190				find.setText(null);
191
192			SearchAndReplace.setSearchString(text);
193			SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
194			SearchAndReplace.hyperSearch(view);
195		} //}}}
196		//{{{ Incremental search
197		else
198		{
199			if(reverse && SearchAndReplace.getRegexp())
200			{
201				GUIUtilities.error(view,"regexp-reverse",null);
202				return;
203			}
204
205			// on enter, start search from end
206			// of current match to find next one
207			int start;
208			JEditTextArea textArea = view.getTextArea();
209			Selection s = textArea.getSelectionAtOffset(
210				textArea.getCaretPosition());
211			if(s == null)
212				start = textArea.getCaretPosition();
213			else if(reverse)
214				start = s.getStart();
215			else
216				start = s.getEnd();
217
218			if(!incrementalSearch(start,reverse))
219			{
220				// not found. start from
221				// beginning
222				if(!incrementalSearch(reverse
223					? view.getBuffer().getLength()
224					: 0,reverse))
225				{
226					// not found at all.
227					view.getStatus().setMessageAndClear(
228						jEdit.getProperty(
229						"view.status.search-not-found"));
230				}
231				else
232				{
233					// inform user search restarted
234					view.getStatus().setMessageAndClear(
235						jEdit.getProperty("view.status.auto-wrap"));
236					// beep if beep property set
237					if(jEdit.getBooleanProperty("search.beepOnSearchAutoWrap"))
238					{
239						getToolkit().beep();
240					}
241				}
242			}
243		} //}}}
244	} //}}}
245
246	//{{{ incrementalSearch() method
247	private boolean incrementalSearch(int start, boolean reverse)
248	{
249		/* For example, if the current fileset is a directory,
250		 * C+g will find the next match within that fileset.
251		 * This can be annoying if you have just done an
252		 * incremental search and want the next occurrence
253		 * in the current buffer. */
254		SearchAndReplace.setSearchFileSet(new CurrentBufferSet());
255		SearchAndReplace.setSearchString(find.getText());
256		SearchAndReplace.setReverseSearch(reverse);
257
258		try
259		{
260			if(SearchAndReplace.find(view,view.getBuffer(),start,false,reverse))
261				return true;
262		}
263		catch(Exception e)
264		{
265			Log.log(Log.DEBUG,this,e);
266
267			// invalid regexp, ignore
268			// return true to avoid annoying beeping while
269			// typing a re
270			return true;
271		}
272
273		return false;
274	} //}}}
275
276	//{{{ timerIncrementalSearch() method
277	private void timerIncrementalSearch(int start, boolean reverse)
278	{
279		this.searchStart = start;
280		this.searchReverse = reverse;
281
282		timer.stop();
283		timer.setRepeats(false);
284		timer.setInitialDelay(150);
285		timer.start();
286	} //}}}
287
288	//}}}
289
290	//{{{ Inner classes
291
292	//{{{ ActionHandler class
293	class ActionHandler implements ActionListener
294	{
295		//{{{ actionPerformed() method
296		public void actionPerformed(ActionEvent evt)
297		{
298			Object source = evt.getSource();
299			if(source == find)
300				find(false);
301			else if(source == hyperSearch)
302			{
303				jEdit.setBooleanProperty("view.search.hypersearch.toggle",
304					hyperSearch.isSelected());
305				update();
306			}
307			else if(source == ignoreCase)
308			{
309				SearchAndReplace.setIgnoreCase(ignoreCase
310					.isSelected());
311			}
312			else if(source == regexp)
313			{
314				SearchAndReplace.setRegexp(regexp
315					.isSelected());
316			}
317			else if(source == close)
318			{
319				view.removeToolBar(SearchBar.this);
320				view.getEditPane().focusOnTextArea();
321			}
322		} //}}}
323	} //}}}
324
325	//{{{ DocumentHandler class
326	class DocumentHandler implements DocumentListener
327	{
328		//{{{ insertUpdate() method
329		public void insertUpdate(DocumentEvent evt)
330		{
331			// on insert, start search from beginning of
332			// current match. This will continue to highlight
333			// the current match until another match is found
334			if(!hyperSearch.isSelected())
335			{
336				int start;
337				JEditTextArea textArea = view.getTextArea();
338				Selection s = textArea.getSelectionAtOffset(
339					textArea.getCaretPosition());
340				if(s == null)
341					start = textArea.getCaretPosition();
342				else
343					start = s.getStart();
344
345				timerIncrementalSearch(start,false);
346			}
347		} //}}}
348
349		//{{{ removeUpdate() method
350		public void removeUpdate(DocumentEvent evt)
351		{
352			// on backspace, restart from beginning
353			if(!hyperSearch.isSelected())
354			{
355				String text = find.getText();
356				if(text.length() != 0)
357				{
358					// don't beep if not found.
359					// subsequent beeps are very
360					// annoying when backspacing an
361					// invalid search string.
362					if(regexp.isSelected())
363					{
364						// reverse regexp search
365						// not supported yet, so
366						// 'simulate' with restart
367						timerIncrementalSearch(0,false);
368					}
369					else
370					{
371						int start;
372						JEditTextArea textArea = view.getTextArea();
373						Selection s = textArea.getSelectionAtOffset(
374							textArea.getCaretPosition());
375						if(s == null)
376							start = textArea.getCaretPosition();
377						else
378							start = s.getStart();
379						timerIncrementalSearch(start,true);
380					}
381				}
382			}
383		} //}}}
384
385		//{{{ changedUpdate() method
386		public void changedUpdate(DocumentEvent evt) {}
387		//}}}
388	} //}}}
389
390	//{{{ KeyHandler class
391	class KeyHandler extends KeyAdapter
392	{
393		public void keyPressed(KeyEvent evt)
394		{
395			switch(evt.getKeyCode())
396			{
397			case KeyEvent.VK_ESCAPE:
398				if(temp)
399				{
400					view.removeToolBar(SearchBar.this);
401				}
402				evt.consume();
403				view.getEditPane().focusOnTextArea();
404				break;
405			case KeyEvent.VK_ENTER:
406				if(evt.isShiftDown())
407				{
408					evt.consume();
409					find(true);
410				}
411				break;
412			}
413		}
414	} //}}}
415
416	//{{{ FocusHandler class
417	class FocusHandler extends FocusAdapter
418	{
419		public void focusLost(FocusEvent e)
420		{
421			getField().addCurrentToHistory();
422		}
423	} //}}}
424
425	//}}}
426}