PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre4/org/gjt/sp/jedit/search/SearchBar.java

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