|
What this is
Other links
The source code/* * CompleteWord.java - Complete word dialog * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2000, 2001 Slava Pestov * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gjt.sp.jedit.gui; //{{{ Imports import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.HashSet; import java.util.TreeSet; import java.util.Set; import org.gjt.sp.jedit.syntax.*; import org.gjt.sp.jedit.textarea.*; import org.gjt.sp.jedit.*; //}}} public class CompleteWord extends JWindow { //{{{ completeWord() method public static void completeWord(View view) { JEditTextArea textArea = view.getTextArea(); Buffer buffer = view.getBuffer(); int caretLine = textArea.getCaretLine(); int caret = textArea.getCaretPosition(); if(!buffer.isEditable()) { textArea.getToolkit().beep(); return; } KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret); String noWordSep = getNonAlphaNumericWordChars( buffer,keywordMap); String word = getWordToComplete(buffer,caretLine, caret,noWordSep); if(word == null) { textArea.getToolkit().beep(); return; } Completion[] completions = getCompletions(buffer,word,caret); if(completions.length == 0) { textArea.getToolkit().beep(); } //{{{ if there is only one competion, insert in buffer else if(completions.length == 1) { Completion c = completions[0]; if(c.text.equals(word)) { textArea.getToolkit().beep(); } else { textArea.setSelectedText(c.text.substring( word.length())); } } //}}} //{{{ show popup if > 1 else { String longestPrefix = MiscUtilities.getLongestPrefix( completions, keywordMap != null ? keywordMap.getIgnoreCase() : false); if (word.length() < longestPrefix.length()) { buffer.insert(caret,longestPrefix.substring( word.length())); } textArea.scrollToCaret(false); Point location = textArea.offsetToXY( caret - word.length()); location.y += textArea.getPainter().getFontMetrics() .getHeight(); SwingUtilities.convertPointToScreen(location, textArea.getPainter()); new CompleteWord(view,longestPrefix, completions,location,noWordSep); } //}}} } //}}} //{{{ CompleteWord constructor public CompleteWord(View view, String word, Completion[] completions, Point location, String noWordSep) { super(view); this.noWordSep = noWordSep; setContentPane(new JPanel(new BorderLayout()) { /** * Returns if this component can be traversed by pressing the * Tab key. This returns false. */ public boolean isManagingFocus() { return false; } /** * Makes the tab key work in Java 1.4. */ public boolean getFocusTraversalKeysEnabled() { return false; } }); this.view = view; this.textArea = view.getTextArea(); this.buffer = view.getBuffer(); this.word = word; words = new JList(completions); words.setVisibleRowCount(Math.min(completions.length,8)); words.addMouseListener(new MouseHandler()); words.setSelectedIndex(0); words.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); words.setCellRenderer(new Renderer()); // stupid scrollbar policy is an attempt to work around // bugs people have been seeing with IBM's JDK -- 7 Sep 2000 JScrollPane scroller = new JScrollPane(words, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); getContentPane().add(scroller, BorderLayout.CENTER); GUIUtilities.requestFocus(this,words); pack(); setLocation(location); setVisible(true); KeyHandler keyHandler = new KeyHandler(); addKeyListener(keyHandler); words.addKeyListener(keyHandler); view.setKeyEventInterceptor(keyHandler); } //}}} //{{{ dispose() method public void dispose() { view.setKeyEventInterceptor(null); super.dispose(); SwingUtilities.invokeLater(new Runnable() { public void run() { textArea.requestFocus(); } }); } //}}} //{{{ Private members //{{{ getNonAlphaNumericWordChars() method private static String getNonAlphaNumericWordChars(Buffer buffer, KeywordMap keywordMap) { // figure out what constitutes a word character and what // doesn't String noWordSep = buffer.getStringProperty("noWordSep"); if(noWordSep == null) noWordSep = ""; if(keywordMap != null) { String keywordNoWordSep = keywordMap.getNonAlphaNumericChars(); if(keywordNoWordSep != null) noWordSep = noWordSep + keywordNoWordSep; } return noWordSep; } //}}} //{{{ getWordToComplete() method private static String getWordToComplete(Buffer buffer, int caretLine, int caret, String noWordSep) { String line = buffer.getLineText(caretLine); int dot = caret - buffer.getLineStartOffset(caretLine); if(dot == 0) return null; char ch = line.charAt(dot-1); if(!Character.isLetterOrDigit(ch) && noWordSep.indexOf(ch) == -1) { // attempting to expand non-word char return null; } int wordStart = TextUtilities.findWordStart(line,dot-1,noWordSep); String word = line.substring(wordStart,dot); if(word.length() == 0) return null; return word; } //}}} //{{{ getCompletions() method private static Completion[] getCompletions(Buffer buffer, String word, int caret) { // build a list of unique words in all visible buffers Set completions = new TreeSet(new MiscUtilities .StringCompare()); Set buffers = new HashSet(); // only complete current buffer's keyword map KeywordMap keywordMap = buffer.getKeywordMapAtOffset(caret); String noWordSep = getNonAlphaNumericWordChars( buffer,keywordMap); View views = jEdit.getFirstView(); while(views != null) { EditPane[] panes = views.getEditPanes(); for(int i = 0; i < panes.length; i++) { Buffer b = panes[i].getBuffer(); if(buffers.contains(b)) continue; buffers.add(b); // only complete current buffer's keyword map KeywordMap _keywordMap; if(b == buffer) _keywordMap = keywordMap; else _keywordMap = null; int offset = (b == buffer ? caret : 0); getCompletions(b,word,keywordMap,noWordSep, offset,completions); } views = views.getNext(); } Completion[] completionArray = (Completion[])completions .toArray(new Completion[completions.size()]); return completionArray; } //}}} //{{{ getCompletions() method private static void getCompletions(Buffer buffer, String word, KeywordMap keywordMap, String noWordSep, int caret, Set completions) { int wordLen = word.length(); //{{{ try to find matching keywords if(keywordMap != null) { String[] keywords = keywordMap.getKeywords(); for(int i = 0; i < keywords.length; i++) { String _keyword = keywords[i]; if(_keyword.regionMatches(keywordMap.getIgnoreCase(), 0,word,0,wordLen)) { Completion keyword = new Completion(_keyword,true); if(!completions.contains(keyword)) { completions.add(keyword); } } } } //}}} //{{{ loop through all lines of current buffer for(int i = 0; i < buffer.getLineCount(); i++) { String line = buffer.getLineText(i); int start = buffer.getLineStartOffset(i); // check for match at start of line if(line.startsWith(word) && caret != start + word.length()) { String _word = completeWord(line,0,noWordSep); Completion comp = new Completion(_word,false); // remove duplicates if(!completions.contains(comp)) { completions.add(comp); } } // check for match inside line int len = line.length() - word.length(); for(int j = 0; j < len; j++) { char c = line.charAt(j); if(!Character.isLetterOrDigit(c) && noWordSep.indexOf(c) == -1) { if(line.regionMatches(j + 1,word,0,wordLen) && caret != start + j + word.length() + 1) { String _word = completeWord(line,j + 1,noWordSep); Completion comp = new Completion(_word,false); // remove duplicates if(!completions.contains(comp)) { completions.add(comp); } } } } } //}}} } //}}} //{{{ completeWord() method private static String completeWord(String line, int offset, String noWordSep) { // '+ 1' so that findWordEnd() doesn't pick up the space at the start int wordEnd = TextUtilities.findWordEnd(line,offset + 1,noWordSep); return line.substring(offset,wordEnd); } //}}} //{{{ Instance variables private View view; private JEditTextArea textArea; private Buffer buffer; private String word; private JList words; private String noWordSep; //}}} //{{{ insertSelected() method private void insertSelected() { textArea.setSelectedText(words.getSelectedValue().toString() .substring(word.length())); dispose(); } //}}} //}}} //{{{ Completion class static class Completion { String text; boolean keyword; Completion(String text, boolean keyword) { this.text = text; this.keyword = keyword; } public String toString() { return text; } public int hashCode() { return text.hashCode(); } public boolean equals(Object obj) { if(obj instanceof Completion) return ((Completion)obj).text.equals(text); else return false; } } //}}} //{{{ Renderer class static class Renderer extends DefaultListCellRenderer { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list,null,index, isSelected,cellHasFocus); Completion comp = (Completion)value; if(index < 9) setText((index + 1) + ": " + comp.text); else if(index == 9) setText("0: " + comp.text); else setText(comp.text); if(comp.keyword) setFont(list.getFont().deriveFont(Font.BOLD)); else setFont(list.getFont()); return this; } } //}}} //{{{ KeyHandler class class KeyHandler extends KeyAdapter { //{{{ keyPressed() method public void keyPressed(KeyEvent evt) { switch(evt.getKeyCode()) { case KeyEvent.VK_TAB: case KeyEvent.VK_ENTER: insertSelected(); evt.consume(); break; case KeyEvent.VK_ESCAPE: dispose(); evt.consume(); break; case KeyEvent.VK_UP: int selected = words.getSelectedIndex(); if(selected == 0) selected = words.getModel().getSize() - 1; else if(getFocusOwner() == words) return; else selected = selected - 1; words.setSelectedIndex(selected); words.ensureIndexIsVisible(selected); evt.consume(); break; case KeyEvent.VK_DOWN: /* int */ selected = words.getSelectedIndex(); if(selected == words.getModel().getSize() - 1) selected = 0; else if(getFocusOwner() == words) return; else selected = selected + 1; words.setSelectedIndex(selected); words.ensureIndexIsVisible(selected); evt.consume(); break; case KeyEvent.VK_BACK_SPACE: if(word.length() == 1) { textArea.backspace(); evt.consume(); dispose(); } else { word = word.substring(0,word.length() - 1); textArea.backspace(); int caret = textArea.getCaretPosition(); Completion[] completions = getCompletions(buffer,word, caret); if(completions.length == 0) { dispose(); return; } words.setListData(completions); words.setSelectedIndex(0); words.setVisibleRowCount(Math.min(completions.length,8)); pack(); evt.consume(); } break; default: if(evt.isActionKey() || evt.isControlDown() || evt.isAltDown() || evt.isMetaDown()) { dispose(); view.processKeyEvent(evt); } break; } } //}}} //{{{ keyTyped() method public void keyTyped(KeyEvent evt) { char ch = evt.getKeyChar(); evt = KeyEventWorkaround.processKeyEvent(evt); if(evt == null) return; if(Character.isDigit(ch)) { int index = ch - '0'; if(index == 0) index = 9; else index--; if(index < words.getModel().getSize()) { words.setSelectedIndex(index); textArea.setSelectedText(words.getModel() .getElementAt(index).toString() .substring(word.length())); dispose(); return; } else /* fall through */; } // \t handled above if(ch != '\b' && ch != '\t') { /* eg, foo |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.