PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/jEdit/tags/jedit-4-0-pre5/org/gjt/sp/jedit/gui/CompleteWord.java

#
Java | 453 lines | 331 code | 64 blank | 58 comment | 70 complexity | 1f97056a4bd245199bfdb640b4e6182e 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. * CompleteWord.java - Complete word dialog
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * 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. package org.gjt.sp.jedit.gui;
  23. //{{{ Imports
  24. import javax.swing.*;
  25. import javax.swing.event.*;
  26. import java.awt.*;
  27. import java.awt.event.*;
  28. import java.util.Vector;
  29. import org.gjt.sp.jedit.syntax.*;
  30. import org.gjt.sp.jedit.textarea.*;
  31. import org.gjt.sp.jedit.*;
  32. //}}}
  33. public class CompleteWord extends JWindow
  34. {
  35. //{{{ completeWord() method
  36. public static void completeWord(View view)
  37. {
  38. JEditTextArea textArea = view.getTextArea();
  39. Buffer buffer = view.getBuffer();
  40. int caretLine = textArea.getCaretLine();
  41. int caret = textArea.getCaretPosition();
  42. if(!buffer.isEditable())
  43. {
  44. textArea.getToolkit().beep();
  45. return;
  46. }
  47. KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret);
  48. String noWordSep = getNonAlphaNumericWordChars(buffer,keywordMap,caret);
  49. String word = getWordToComplete(buffer,caretLine,caret,noWordSep);
  50. if(word == null)
  51. {
  52. textArea.getToolkit().beep();
  53. return;
  54. }
  55. Vector completions = getCompletions(buffer,word,keywordMap,
  56. noWordSep,caret);
  57. if(completions.size() == 0)
  58. textArea.getToolkit().beep();
  59. //{{{ if there is only one competion, insert in buffer
  60. else if(completions.size() == 1)
  61. {
  62. textArea.setSelectedText(completions
  63. .elementAt(0).toString()
  64. .substring(word.length()));
  65. } //}}}
  66. //{{{ show popup if > 1
  67. else
  68. {
  69. Point location = textArea.offsetToXY(caret - word.length());
  70. location.y += textArea.getPainter().getFontMetrics()
  71. .getHeight();
  72. SwingUtilities.convertPointToScreen(location,
  73. textArea.getPainter());
  74. new CompleteWord(view,word,completions,location);
  75. } //}}}
  76. } //}}}
  77. //{{{ CompleteWord constructor
  78. public CompleteWord(View view, String word, Vector completions, Point location)
  79. {
  80. super(view);
  81. this.view = view;
  82. this.textArea = view.getTextArea();
  83. this.buffer = view.getBuffer();
  84. this.word = word;
  85. words = new JList(completions);
  86. words.setFont(UIManager.getFont("TextArea.font"));
  87. words.setVisibleRowCount(Math.min(completions.size(),8));
  88. words.addMouseListener(new MouseHandler());
  89. words.setSelectedIndex(0);
  90. words.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  91. words.setCellRenderer(new Renderer());
  92. // stupid scrollbar policy is an attempt to work around
  93. // bugs people have been seeing with IBM's JDK -- 7 Sep 2000
  94. JScrollPane scroller = new JScrollPane(words,
  95. JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
  96. JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
  97. getContentPane().add(scroller, BorderLayout.CENTER);
  98. GUIUtilities.requestFocus(this,words);
  99. pack();
  100. setLocation(location);
  101. show();
  102. KeyHandler keyHandler = new KeyHandler();
  103. addKeyListener(keyHandler);
  104. words.addKeyListener(keyHandler);
  105. view.setKeyEventInterceptor(keyHandler);
  106. } //}}}
  107. //{{{ dispose() method
  108. public void dispose()
  109. {
  110. view.setKeyEventInterceptor(null);
  111. super.dispose();
  112. SwingUtilities.invokeLater(new Runnable()
  113. {
  114. public void run()
  115. {
  116. textArea.requestFocus();
  117. }
  118. });
  119. } //}}}
  120. //{{{ Private members
  121. //{{{ getNonAlphaNumericWordChars() method
  122. private static String getNonAlphaNumericWordChars(Buffer buffer,
  123. KeywordMap keywordMap, int caret)
  124. {
  125. // figure out what constitutes a word character and what
  126. // doesn't
  127. String noWordSep = buffer.getStringProperty("noWordSep");
  128. if(noWordSep == null)
  129. noWordSep = "";
  130. if(keywordMap != null)
  131. {
  132. String keywordNoWordSep = keywordMap.getNonAlphaNumericChars();
  133. if(keywordNoWordSep != null)
  134. noWordSep = noWordSep + keywordNoWordSep;
  135. }
  136. return noWordSep;
  137. } //}}}
  138. //{{{ getWordToComplete() method
  139. private static String getWordToComplete(Buffer buffer, int caretLine,
  140. int caret, String noWordSep)
  141. {
  142. String line = buffer.getLineText(caretLine);
  143. int dot = caret - buffer.getLineStartOffset(caretLine);
  144. if(dot == 0)
  145. return null;
  146. char ch = line.charAt(dot-1);
  147. if(!Character.isLetterOrDigit(ch)
  148. && noWordSep.indexOf(ch) == -1)
  149. {
  150. // attempting to expand non-word char
  151. return null;
  152. }
  153. int wordStart = TextUtilities.findWordStart(line,dot-1,noWordSep);
  154. String word = line.substring(wordStart,dot);
  155. if(word.length() == 0)
  156. return null;
  157. return word;
  158. } //}}}
  159. //{{{ getCompletions() method
  160. private static Vector getCompletions(Buffer buffer, String word,
  161. KeywordMap keywordMap, String noWordSep, int caret)
  162. {
  163. Vector completions = new Vector();
  164. int wordLen = word.length();
  165. //{{{ try to find matching keywords
  166. if(keywordMap != null)
  167. {
  168. String[] keywords = keywordMap.getKeywords();
  169. for(int i = 0; i < keywords.length; i++)
  170. {
  171. String _keyword = keywords[i];
  172. if(_keyword.regionMatches(keywordMap.getIgnoreCase(),
  173. 0,word,0,wordLen))
  174. {
  175. Completion keyword = new Completion(_keyword,true);
  176. if(completions.indexOf(keyword) == -1)
  177. completions.addElement(keyword);
  178. }
  179. }
  180. } //}}}
  181. //{{{ loop through all lines of current buffer
  182. for(int i = 0; i < buffer.getLineCount(); i++)
  183. {
  184. String line = buffer.getLineText(i);
  185. int start = buffer.getLineStartOffset(i);
  186. // check for match at start of line
  187. if(line.startsWith(word) && caret != start + word.length())
  188. {
  189. String _word = completeWord(line,0,noWordSep);
  190. if(_word.length() != wordLen)
  191. {
  192. Completion comp = new Completion(_word,false);
  193. // remove duplicates
  194. if(completions.indexOf(comp) == -1)
  195. completions.addElement(comp);
  196. }
  197. }
  198. // check for match inside line
  199. int len = line.length() - word.length();
  200. for(int j = 0; j < len; j++)
  201. {
  202. char c = line.charAt(j);
  203. if(!Character.isLetterOrDigit(c) && noWordSep.indexOf(c) == -1)
  204. {
  205. if(line.regionMatches(j + 1,word,0,wordLen)
  206. && caret != start + j + word.length() + 1)
  207. {
  208. String _word = completeWord(line,j + 1,noWordSep);
  209. if(_word.length() != wordLen)
  210. {
  211. Completion comp = new Completion(_word,false);
  212. // remove duplicates
  213. if(completions.indexOf(comp) == -1)
  214. completions.addElement(comp);
  215. }
  216. }
  217. }
  218. }
  219. } //}}}
  220. // sort completion list
  221. MiscUtilities.quicksort(completions,new MiscUtilities.StringICaseCompare());
  222. return completions;
  223. } //}}}
  224. //{{{ completeWord() method
  225. private static String completeWord(String line, int offset, String noWordSep)
  226. {
  227. // '+ 1' so that findWordEnd() doesn't pick up the space at the start
  228. int wordEnd = TextUtilities.findWordEnd(line,offset + 1,noWordSep);
  229. return line.substring(offset,wordEnd);
  230. } //}}}
  231. //{{{ Instance variables
  232. private View view;
  233. private JEditTextArea textArea;
  234. private Buffer buffer;
  235. private String word;
  236. private JList words;
  237. //}}}
  238. //{{{ insertSelected() method
  239. private void insertSelected()
  240. {
  241. textArea.setSelectedText(words.getSelectedValue().toString()
  242. .substring(word.length()));
  243. dispose();
  244. } //}}}
  245. //}}}
  246. //{{{ Completion class
  247. static class Completion
  248. {
  249. String text;
  250. boolean keyword;
  251. Completion(String text, boolean keyword)
  252. {
  253. this.text = text;
  254. this.keyword = keyword;
  255. }
  256. public String toString()
  257. {
  258. return text;
  259. }
  260. public boolean equals(Object obj)
  261. {
  262. if(obj instanceof Completion)
  263. return ((Completion)obj).text.equals(text);
  264. else
  265. return false;
  266. }
  267. } //}}}
  268. //{{{ Renderer class
  269. static class Renderer extends DefaultListCellRenderer
  270. {
  271. public Component getListCellRendererComponent(JList list, Object value,
  272. int index, boolean isSelected, boolean cellHasFocus)
  273. {
  274. super.getListCellRendererComponent(list,value,index,
  275. isSelected,cellHasFocus);
  276. Completion comp = (Completion)value;
  277. if(comp.keyword)
  278. setFont(list.getFont().deriveFont(Font.BOLD));
  279. else
  280. setFont(list.getFont());
  281. return this;
  282. }
  283. } //}}}
  284. //{{{ KeyHandler class
  285. class KeyHandler extends KeyAdapter
  286. {
  287. //{{{ keyPressed() method
  288. public void keyPressed(KeyEvent evt)
  289. {
  290. switch(evt.getKeyCode())
  291. {
  292. // doesn't work in 1.4?
  293. //case KeyEvent.VK_TAB:
  294. case KeyEvent.VK_ENTER:
  295. insertSelected();
  296. evt.consume();
  297. break;
  298. case KeyEvent.VK_ESCAPE:
  299. dispose();
  300. evt.consume();
  301. break;
  302. case KeyEvent.VK_UP:
  303. int selected = words.getSelectedIndex();
  304. if(selected == 0)
  305. selected = words.getModel().getSize() - 1;
  306. else if(getFocusOwner() == words)
  307. return;
  308. else
  309. selected = selected - 1;
  310. words.setSelectedIndex(selected);
  311. words.ensureIndexIsVisible(selected);
  312. evt.consume();
  313. break;
  314. case KeyEvent.VK_DOWN:
  315. /* int */ selected = words.getSelectedIndex();
  316. if(selected == words.getModel().getSize() - 1)
  317. selected = 0;
  318. else if(getFocusOwner() == words)
  319. return;
  320. else
  321. selected = selected + 1;
  322. words.setSelectedIndex(selected);
  323. words.ensureIndexIsVisible(selected);
  324. evt.consume();
  325. break;
  326. case KeyEvent.VK_BACK_SPACE:
  327. if(word.length() == 1)
  328. {
  329. textArea.backspace();
  330. evt.consume();
  331. dispose();
  332. }
  333. else
  334. {
  335. word = word.substring(0,word.length() - 1);
  336. textArea.backspace();
  337. int caret = textArea.getCaretPosition();
  338. KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret);
  339. String noWordSep = getNonAlphaNumericWordChars(buffer,keywordMap,caret);
  340. Vector completions = getCompletions(buffer,word,
  341. keywordMap,noWordSep,caret);
  342. if(completions.size() == 0)
  343. dispose();
  344. words.setListData(completions);
  345. words.setSelectedIndex(0);
  346. evt.consume();
  347. }
  348. break;
  349. default:
  350. if(evt.isActionKey())
  351. {
  352. dispose();
  353. view.processKeyEvent(evt);
  354. }
  355. break;
  356. }
  357. } //}}}
  358. //{{{ keyTyped() method
  359. public void keyTyped(KeyEvent evt)
  360. {
  361. char ch = evt.getKeyChar();
  362. evt = KeyEventWorkaround.processKeyEvent(evt);
  363. if(evt == null)
  364. return;
  365. else if(ch != '\b')
  366. {
  367. word = word + ch;
  368. textArea.userInput(ch);
  369. int caret = textArea.getCaretPosition();
  370. KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret);
  371. String noWordSep = getNonAlphaNumericWordChars(buffer,keywordMap,caret);
  372. Vector completions = getCompletions(buffer,word,keywordMap,
  373. noWordSep,caret);
  374. if(completions.size() == 0)
  375. dispose();
  376. words.setListData(completions);
  377. words.setSelectedIndex(0);
  378. }
  379. } //}}}
  380. } //}}}
  381. //{{{ MouseHandler class
  382. class MouseHandler extends MouseAdapter
  383. {
  384. public void mouseClicked(MouseEvent evt)
  385. {
  386. insertSelected();
  387. }
  388. } //}}}
  389. }