PageRenderTime 52ms CodeModel.GetById 12ms app.highlight 32ms RepoModel.GetById 2ms app.codeStats 0ms

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

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