1 22 23 package org.gjt.sp.jedit.gui; 24 25 import javax.swing.*; 27 import java.awt.*; 28 import java.awt.event.*; 29 import java.util.HashSet ; 30 import java.util.TreeSet ; 31 import java.util.Set ; 32 import org.gjt.sp.jedit.syntax.*; 33 import org.gjt.sp.jedit.textarea.*; 34 import org.gjt.sp.jedit.*; 35 import org.gjt.sp.util.StandardUtilities; 36 38 41 42 public class CompleteWord extends JWindow 43 { 44 public static void completeWord(View view) 46 { 47 JEditTextArea textArea = view.getTextArea(); 48 Buffer buffer = view.getBuffer(); 49 int caretLine = textArea.getCaretLine(); 50 int caret = textArea.getCaretPosition(); 51 52 if(!buffer.isEditable()) 53 { 54 textArea.getToolkit().beep(); 55 return; 56 } 57 58 KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret); 59 String noWordSep = getNonAlphaNumericWordChars( 60 buffer,keywordMap); 61 String word = getWordToComplete(buffer,caretLine, 62 caret,noWordSep); 63 if(word == null) 64 { 65 textArea.getToolkit().beep(); 66 return; 67 } 68 69 Completion[] completions = getCompletions(buffer,word,caret); 70 71 if(completions.length == 0) 72 { 73 textArea.getToolkit().beep(); 74 } 75 else if(completions.length == 1) 77 { 78 Completion c = completions[0]; 79 80 if(c.text.equals(word)) 81 { 82 textArea.getToolkit().beep(); 83 } 84 else 85 { 86 textArea.setSelectedText(c.text.substring( 87 word.length())); 88 } 89 } else 92 { 93 String longestPrefix = MiscUtilities.getLongestPrefix( 94 completions, 95 keywordMap != null 96 ? keywordMap.getIgnoreCase() 97 : false); 98 99 if (word.length() < longestPrefix.length()) 100 { 101 buffer.insert(caret,longestPrefix.substring( 102 word.length())); 103 } 104 105 textArea.scrollToCaret(false); 106 Point location = textArea.offsetToXY( 107 caret - word.length()); 108 location.y += textArea.getPainter().getFontMetrics() 109 .getHeight(); 110 111 SwingUtilities.convertPointToScreen(location, 112 textArea.getPainter()); 113 new CompleteWord(view,longestPrefix, 114 completions,location,noWordSep); 115 } } 118 public static Point fitInScreen(Point p, Window w, int lineHeight) 120 { 121 Rectangle screenSize = w.getGraphicsConfiguration().getBounds(); 122 if(p.y + w.getHeight() >= screenSize.height) 123 p.y = p.y - w.getHeight() - lineHeight; 124 return p; 125 } 127 public CompleteWord(View view, String word, Completion[] completions, 129 Point location, String noWordSep) 130 { 131 super(view); 132 133 this.noWordSep = noWordSep; 134 135 setContentPane(new JPanel(new BorderLayout()) 136 { 137 141 public boolean isManagingFocus() 142 { 143 return false; 144 } 145 146 149 public boolean getFocusTraversalKeysEnabled() 150 { 151 return false; 152 } 153 }); 154 155 this.view = view; 156 this.textArea = view.getTextArea(); 157 this.buffer = view.getBuffer(); 158 this.word = word; 159 160 words = new JList(completions); 161 162 words.setVisibleRowCount(Math.min(completions.length,8)); 163 164 words.addMouseListener(new MouseHandler()); 165 words.setSelectedIndex(0); 166 words.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 167 words.setCellRenderer(new Renderer()); 168 169 JScrollPane scroller = new JScrollPane(words, 172 ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, 173 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 174 175 getContentPane().add(scroller, BorderLayout.CENTER); 176 177 GUIUtilities.requestFocus(this,words); 178 179 pack(); 180 setLocation(fitInScreen(location,this, 181 textArea.getPainter().getFontMetrics() 182 .getHeight())); 183 setVisible(true); 184 185 KeyHandler keyHandler = new KeyHandler(); 186 addKeyListener(keyHandler); 187 words.addKeyListener(keyHandler); 188 view.setKeyEventInterceptor(keyHandler); 189 } 191 public void dispose() 193 { 194 view.setKeyEventInterceptor(null); 195 super.dispose(); 196 SwingUtilities.invokeLater(new Runnable () 197 { 198 public void run() 199 { 200 textArea.requestFocus(); 201 } 202 }); 203 } 205 207 private static String getNonAlphaNumericWordChars(Buffer buffer, 209 KeywordMap keywordMap) 210 { 211 String noWordSep = buffer.getStringProperty("noWordSep"); 214 if(noWordSep == null) 215 noWordSep = ""; 216 if(keywordMap != null) 217 { 218 String keywordNoWordSep = keywordMap.getNonAlphaNumericChars(); 219 if(keywordNoWordSep != null) 220 noWordSep += keywordNoWordSep; 221 } 222 223 return noWordSep; 224 } 226 private static String getWordToComplete(Buffer buffer, int caretLine, 228 int caret, String noWordSep) 229 { 230 String line = buffer.getLineText(caretLine); 231 int dot = caret - buffer.getLineStartOffset(caretLine); 232 if(dot == 0) 233 return null; 234 235 char ch = line.charAt(dot-1); 236 if(!Character.isLetterOrDigit(ch) 237 && noWordSep.indexOf(ch) == -1) 238 { 239 return null; 241 } 242 243 int wordStart = TextUtilities.findWordStart(line,dot-1,noWordSep); 244 String word = line.substring(wordStart,dot); 245 if(word.length() == 0) 246 return null; 247 248 return word; 249 } 251 private static Completion[] getCompletions(Buffer buffer, String word, 253 int caret) 254 { 255 Set <Completion> completions = new TreeSet <Completion>(new StandardUtilities 257 .StringCompare()); 258 Set <Buffer> buffers = new HashSet <Buffer>(); 259 260 KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret); 262 String noWordSep = getNonAlphaNumericWordChars( 263 buffer,keywordMap); 264 265 View views = jEdit.getFirstView(); 266 while(views != null) 267 { 268 EditPane[] panes = views.getEditPanes(); 269 for(int i = 0; i < panes.length; i++) 270 { 271 Buffer b = panes[i].getBuffer(); 272 if(buffers.contains(b)) 273 continue; 274 275 buffers.add(b); 276 277 KeywordMap _keywordMap; 279 if(b == buffer) 280 _keywordMap = keywordMap; 281 else 282 _keywordMap = null; 283 284 int offset = (b == buffer ? caret : 0); 285 286 getCompletions(b,word,keywordMap,noWordSep, 287 offset,completions); 288 } 289 290 views = views.getNext(); 291 } 292 293 Completion[] completionArray = completions 294 .toArray(new Completion[completions.size()]); 295 296 return completionArray; 297 } 299 private static void getCompletions(Buffer buffer, String word, 301 KeywordMap keywordMap, String noWordSep, int caret, 302 Set <Completion> completions) 303 { 304 int wordLen = word.length(); 305 306 if(keywordMap != null) 308 { 309 String [] keywords = keywordMap.getKeywords(); 310 for(int i = 0; i < keywords.length; i++) 311 { 312 String _keyword = keywords[i]; 313 if(_keyword.regionMatches(keywordMap.getIgnoreCase(), 314 0,word,0,wordLen)) 315 { 316 Completion keyword = new Completion(_keyword,true); 317 if(!completions.contains(keyword)) 318 { 319 completions.add(keyword); 320 } 321 } 322 } 323 } 325 for(int i = 0; i < buffer.getLineCount(); i++) 327 { 328 String line = buffer.getLineText(i); 329 int start = buffer.getLineStartOffset(i); 330 331 333 if(line.startsWith(word) && caret != start + word.length()) 334 { 335 String _word = completeWord(line,0,noWordSep); 336 Completion comp = new Completion(_word,false); 337 338 if(!completions.contains(comp)) 340 { 341 completions.add(comp); 342 } 343 } 344 345 int len = line.length() - word.length(); 347 for(int j = 0; j < len; j++) 348 { 349 char c = line.charAt(j); 350 if(!Character.isLetterOrDigit(c) && noWordSep.indexOf(c) == -1) 351 { 352 if(line.regionMatches(j + 1,word,0,wordLen) 353 && caret != start + j + word.length() + 1) 354 { 355 String _word = completeWord(line,j + 1,noWordSep); 356 Completion comp = new Completion(_word,false); 357 358 if(!completions.contains(comp)) 360 { 361 completions.add(comp); 362 } 363 } 364 } 365 } 366 } } 369 private static String completeWord(String line, int offset, String noWordSep) 371 { 372 int wordEnd = TextUtilities.findWordEnd(line,offset + 1,noWordSep); 374 return line.substring(offset,wordEnd); 375 } 377 private View view; 379 private JEditTextArea textArea; 380 private Buffer buffer; 381 private String word; 382 private JList words; 383 private String noWordSep; 384 386 private void insertSelected() 388 { 389 textArea.setSelectedText(words.getSelectedValue().toString() 390 .substring(word.length())); 391 dispose(); 392 } 394 396 static class Completion 398 { 399 final String text; 400 final boolean keyword; 401 402 Completion(String text, boolean keyword) 403 { 404 this.text = text; 405 this.keyword = keyword; 406 } 407 408 public String toString() 409 { 410 return text; 411 } 412 413 public int hashCode() 414 { 415 return text.hashCode(); 416 } 417 418 public boolean equals(Object obj) 419 { 420 if(obj instanceof Completion) 421 return ((Completion)obj).text.equals(text); 422 else 423 return false; 424 } 425 } 427 static class Renderer extends DefaultListCellRenderer 429 { 430 public Component getListCellRendererComponent(JList list, Object value, 431 int index, boolean isSelected, boolean cellHasFocus) 432 { 433 super.getListCellRendererComponent(list,null,index, 434 isSelected,cellHasFocus); 435 436 Completion comp = (Completion)value; 437 438 if(index < 9) 439 setText((index + 1) + ": " + comp.text); 440 else if(index == 9) 441 setText("0: " + comp.text); 442 else 443 setText(comp.text); 444 445 if(comp.keyword) 446 setFont(list.getFont().deriveFont(Font.BOLD)); 447 else 448 setFont(list.getFont()); 449 450 return this; 451 } 452 } 454 class KeyHandler extends KeyAdapter 456 { 457 public void keyPressed(KeyEvent evt) 459 { 460 int selected = words.getSelectedIndex(); 461 int numRows = words.getVisibleRowCount()-1; 462 int newSelect = -1; 463 464 switch(evt.getKeyCode()) 465 { 466 467 case KeyEvent.VK_TAB: 468 case KeyEvent.VK_ENTER: 469 insertSelected(); 470 evt.consume(); 471 break; 472 case KeyEvent.VK_ESCAPE: 473 dispose(); 474 evt.consume(); 475 break; 476 case KeyEvent.VK_UP: 477 if (getFocusOwner() == words) return; 478 evt.consume(); 479 if(selected == 0) return; 480 selected--; 481 words.setSelectedIndex(selected); 482 words.ensureIndexIsVisible(selected); 483 break; 484 case KeyEvent.VK_DOWN: 485 if(getFocusOwner() == words) return; 486 evt.consume(); 487 if(selected >= words.getModel().getSize()) break; 488 selected++; 489 words.setSelectedIndex(selected); 490 words.ensureIndexIsVisible(selected); 491 break; 492 case KeyEvent.VK_PAGE_UP: 493 newSelect = selected - numRows; 494 if (newSelect < 0) newSelect = 0; 495 words.setSelectedIndex(newSelect); 496 words.ensureIndexIsVisible(newSelect); 497 evt.consume(); 498 break; 499 case KeyEvent.VK_PAGE_DOWN: 500 newSelect = selected + numRows; 501 if (newSelect >= words.getModel().getSize()) newSelect = words.getModel().getSize() - 1; 502 words.setSelectedIndex(newSelect); 503 words.ensureIndexIsVisible(newSelect); 504 evt.consume(); 505 break; 506 507 case KeyEvent.VK_BACK_SPACE: 508 if(word.length() == 1) 509 { 510 textArea.backspace(); 511 evt.consume(); 512 dispose(); 513 } 514 else 515 { 516 word = word.substring(0,word.length() - 1); 517 textArea.backspace(); 518 int caret = textArea.getCaretPosition(); 519 520 Completion[] completions 521 = getCompletions(buffer,word, 522 caret); 523 524 if(completions.length == 0) 525 { 526 dispose(); 527 return; 528 } 529 530 words.setListData(completions); 531 words.setSelectedIndex(0); 532 words.setVisibleRowCount(Math.min(completions.length,8)); 533 534 pack(); 535 536 evt.consume(); 537 } 538 break; 539 default: 540 if(evt.isActionKey() 541 || evt.isControlDown() 542 || evt.isAltDown() 543 || evt.isMetaDown()) 544 { 545 dispose(); 546 view.getInputHandler().processKeyEvent(evt, View.VIEW, false); 547 } 548 break; 549 } 550 551 552 } 554 public void keyTyped(KeyEvent evt) 556 { 557 char ch = evt.getKeyChar(); 558 evt = KeyEventWorkaround.processKeyEvent(evt); 559 if(evt == null) 560 return; 561 562 if(Character.isDigit(ch)) 563 { 564 int index = ch - '0'; 565 if(index == 0) 566 index = 9; 567 else 568 index--; 569 if(index < words.getModel().getSize()) 570 { 571 words.setSelectedIndex(index); 572 textArea.setSelectedText(words.getModel() 573 .getElementAt(index).toString() 574 .substring(word.length())); 575 dispose(); 576 return; 577 } 578 else 579 ; 580 } 581 582 if(ch != '\b' && ch != '\t') 584 { 585 586 if(!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1) 587 { 588 insertSelected(); 589 textArea.userInput(ch); 590 dispose(); 591 return; 592 } 593 594 textArea.userInput(ch); 595 596 word += ch; 597 int caret = textArea.getCaretPosition(); 598 599 Completion[] completions = getCompletions( 600 buffer,word,caret); 601 602 if(completions.length == 0) 603 { 604 dispose(); 605 return; 606 } 607 608 words.setListData(completions); 609 words.setSelectedIndex(0); 610 words.setVisibleRowCount(Math.min(completions.length,8)); 611 } 612 } } 615 class MouseHandler extends MouseAdapter 617 { 618 public void mouseClicked(MouseEvent evt) 619 { 620 evt.consume(); 621 insertSelected(); 622 } 623 } } 625 | Popular Tags |