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