diff -Nru autocomplete-2.5.0/build.xml autocomplete-2.5.3/build.xml --- autocomplete-2.5.0/build.xml 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/build.xml 2014-06-29 18:45:32.000000000 +0000 @@ -23,7 +23,7 @@ - + diff -Nru autocomplete-2.5.0/debian/changelog autocomplete-2.5.3/debian/changelog --- autocomplete-2.5.0/debian/changelog 2013-10-21 17:52:44.000000000 +0000 +++ autocomplete-2.5.3/debian/changelog 2017-10-18 12:08:49.000000000 +0000 @@ -1,3 +1,18 @@ +autocomplete (2.5.3-1) unstable; urgency=medium + + * Team upload. + * New upstream version 2.5.3. + * Switch to compat level 10. + * Use copyright format 1.0. + * Declare compliance with Debian Policy 4.1.1. + * Use canonical Vcs-fields. + * Update pom.xml to version 2.5.3. + * Remove empty TODOs file. + * Update watch file. The project has moved to Github. + * Update Homepage field and point to new home at Github. + + -- Markus Koschany Wed, 18 Oct 2017 14:08:49 +0200 + autocomplete (2.5.0-1) unstable; urgency=low * new upstream release diff -Nru autocomplete-2.5.0/debian/compat autocomplete-2.5.3/debian/compat --- autocomplete-2.5.0/debian/compat 2013-10-20 17:20:22.000000000 +0000 +++ autocomplete-2.5.3/debian/compat 2017-10-18 12:08:49.000000000 +0000 @@ -1 +1 @@ -7 +10 diff -Nru autocomplete-2.5.0/debian/control autocomplete-2.5.3/debian/control --- autocomplete-2.5.0/debian/control 2013-10-21 18:50:00.000000000 +0000 +++ autocomplete-2.5.3/debian/control 2017-10-18 12:08:49.000000000 +0000 @@ -3,12 +3,12 @@ Priority: optional Maintainer: Debian Java Maintainers Uploaders: Benjamin Mesing -Build-Depends: debhelper (>= 9), javahelper (>= 0.4), maven-repo-helper, ant +Build-Depends: debhelper (>= 10), javahelper (>= 0.4), maven-repo-helper, ant Build-Depends-Indep: default-jdk, default-jdk-doc, librsyntaxtextarea-java (>= 2.5), librsyntaxtextarea-java-doc (>= 2.5) -Standards-Version: 3.9.4 -Vcs-Git: git://git.debian.org/git/pkg-java/autocomplete.git -Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-java/autocomplete.git -Homepage: http://fifesoft.com/autocomplete/ +Standards-Version: 4.1.1 +Vcs-Git: https://anonscm.debian.org/git/pkg-java/autocomplete.git +Vcs-Browser: https://anonscm.debian.org/git/pkg-java/autocomplete.git +Homepage: https://github.com/bobbylight/AutoComplete Package: libautocomplete-java Architecture: all diff -Nru autocomplete-2.5.0/debian/copyright autocomplete-2.5.3/debian/copyright --- autocomplete-2.5.0/debian/copyright 2013-10-21 17:33:05.000000000 +0000 +++ autocomplete-2.5.3/debian/copyright 2017-10-18 12:08:49.000000000 +0000 @@ -1,18 +1,18 @@ -Format: http://dep.debian.net/deps/dep5/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: AutoComplete Upstream-Contact: Robert Futrell Source: http://fifesoft.com/autocomplete/ Files: * Copyright: 2013, Robert Futrell -License: modified BSD license +License: modified-BSD-license Files: debian/* Copyright: 2011, Vladimir Kotov 2013, Benjamin Mesing License: LGPL-2.1+ -License: modified BSD license +License: modified-BSD-license Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright diff -Nru autocomplete-2.5.0/debian/pom.xml autocomplete-2.5.3/debian/pom.xml --- autocomplete-2.5.0/debian/pom.xml 2013-10-20 17:26:59.000000000 +0000 +++ autocomplete-2.5.3/debian/pom.xml 2017-10-18 12:08:49.000000000 +0000 @@ -4,24 +4,24 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - - com.fifesoft - rtext-root-pom - 3 - ../../pom.xml - + + com.fifesoft + rtext-root-pom + 3 + ../../pom.xml + com.fifesoft autocomplete - 2.5.0 + 2.5.3 jar AutoComplete - - AutoComplete is a library allowing you to add IDE-like auto-completion (aka "code completion" or - "Intellisense") to any Swing JTextComponent. Special integration is added for RSyntaxTextArea, since - this feature is commonly needed when editing source code. Features include: Drop-down completion - choice list. Optional companion "description" window, complete with full HTML support and navigable - with hyperlinks. Optional parameter completion assistance for functions and methods, ala Eclipse and + + AutoComplete is a library allowing you to add IDE-like auto-completion (aka "code completion" or + "Intellisense") to any Swing JTextComponent. Special integration is added for RSyntaxTextArea, since + this feature is commonly needed when editing source code. Features include: Drop-down completion + choice list. Optional companion "description" window, complete with full HTML support and navigable + with hyperlinks. Optional parameter completion assistance for functions and methods, ala Eclipse and NetBeans. Completion information is typically specified in an XML file, but can even be dynamic. 2003 diff -Nru autocomplete-2.5.0/debian/rules autocomplete-2.5.3/debian/rules --- autocomplete-2.5.0/debian/rules 2013-10-21 18:33:17.000000000 +0000 +++ autocomplete-2.5.3/debian/rules 2017-10-18 12:08:49.000000000 +0000 @@ -5,10 +5,10 @@ %: - dh $@ --with javahelper --with jh_maven_repo_helper + dh $@ --with javahelper --with jh_maven_repo_helper get-orig-source: - git clone https://github.com/bobbylight/AutoComplete.git + git clone https://github.com/bobbylight/AutoComplete.git ( cd AutoComplete ; git archive -9 --prefix=autocomplete-$(VERSION)/ -o ../autocomplete_$(VERSION).orig.tar.gz $(VERSION) ) rm -rf AutoComplete diff -Nru autocomplete-2.5.0/debian/watch autocomplete-2.5.3/debian/watch --- autocomplete-2.5.0/debian/watch 2013-10-20 17:20:22.000000000 +0000 +++ autocomplete-2.5.3/debian/watch 2017-10-18 12:08:49.000000000 +0000 @@ -1,2 +1,2 @@ -version=3 -http://sf.net/rsyntaxtextarea/autocomplete_([\d\.]+)_Source\.zip debian debian/orig-tar.sh +version=4 +https://github.com/bobbylight/AutoComplete/releases /bobbylight/AutoComplete/archive/@ANY_VERSION@.tar.gz diff -Nru autocomplete-2.5.0/.gitignore autocomplete-2.5.3/.gitignore --- autocomplete-2.5.0/.gitignore 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/.gitignore 2014-06-29 18:45:32.000000000 +0000 @@ -2,5 +2,5 @@ bin dist javadoc -autocomplete_*_Source.zip +autocomplete_*.zip diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/AbstractCompletion.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/AbstractCompletion.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/AbstractCompletion.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/AbstractCompletion.java 2014-06-29 18:45:32.000000000 +0000 @@ -36,6 +36,11 @@ private CompletionProvider provider; /** + * The icon to use for this completion. + */ + private Icon icon; + + /** * The relevance of this completion. Completion instances with higher * "relevance" values are inserted higher into the list of possible * completions than those with lower values. Completion instances with @@ -49,12 +54,24 @@ * * @param provider The provider that created this completion. */ - public AbstractCompletion(CompletionProvider provider) { + protected AbstractCompletion(CompletionProvider provider) { this.provider = provider; } /** + * Constructor. + * + * @param provider The provider that created this completion. + * @param icon The icon for this completion. + */ + protected AbstractCompletion(CompletionProvider provider, Icon icon) { + this(provider); + setIcon(icon); + } + + + /** * {@inheritDoc} */ public int compareTo(Completion c2) { @@ -77,13 +94,10 @@ /** - * The default implementation returns null. Subclasses - * who wish to display an icon can override this method. - * - * @return The icon for this completion. + * {@inheritDoc} */ public Icon getIcon() { - return null; + return icon; } @@ -127,6 +141,17 @@ } + /** + * Sets the icon to use for this completion. + * + * @param icon The icon to use. + * @see #getIcon() + */ + public void setIcon(Icon icon) { + this.icon = icon; + } + + /** * Sets the relevance of this completion. * diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/AbstractCompletionProvider.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/AbstractCompletionProvider.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/AbstractCompletionProvider.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/AbstractCompletionProvider.java 2014-06-29 18:45:32.000000000 +0000 @@ -13,6 +13,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; + import javax.swing.text.JTextComponent; @@ -46,6 +47,7 @@ public AbstractCompletionProvider() { comparator = new CaseInsensitiveComparator(); clearParameterizedCompletionParams(); + completions = new ArrayList(); } @@ -229,14 +231,15 @@ * against a String lexicographically, ignoring case. */ @SuppressWarnings("rawtypes") - protected static class CaseInsensitiveComparator implements Comparator, + public static class CaseInsensitiveComparator implements Comparator, Serializable { public int compare(Object o1, Object o2) { - Completion c = (Completion)o1; - // o2.toString() needed to help compile with 1.5+. - return String.CASE_INSENSITIVE_ORDER.compare( - c.getInputText(), o2.toString()); + String s1 = o1 instanceof String ? (String)o1 : + ((Completion)o1).getInputText(); + String s2 = o2 instanceof String ? (String)o2 : + ((Completion)o2).getInputText(); + return String.CASE_INSENSITIVE_ORDER.compare(s1, s2); } } diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java 2014-06-29 18:45:32.000000000 +0000 @@ -101,6 +101,8 @@ private int lastLine; + private boolean keyBindingsInstalled; + private KeyActionPair escapeKap; private KeyActionPair upKap; private KeyActionPair downKap; @@ -321,6 +323,11 @@ if (AutoCompletion.getDebug()) { System.out.println("PopupWindow: Installing keybindings"); } + if (keyBindingsInstalled) { + System.err.println("Error: key bindings were already installed"); + Thread.dumpStack(); + return; + } if (escapeKap==null) { // Lazily create actions. createKeyActionPairs(); @@ -356,6 +363,8 @@ comp.addCaretListener(this); + keyBindingsInstalled = true; + } @@ -733,6 +742,9 @@ if (AutoCompletion.getDebug()) { System.out.println("PopupWindow: Removing keybindings"); } + if (!keyBindingsInstalled) { + return; + } JTextComponent comp = ac.getTextComponent(); InputMap im = comp.getInputMap(); @@ -757,6 +769,8 @@ comp.removeCaretListener(this); + keyBindingsInstalled = false; + } @@ -946,8 +960,7 @@ setPrototypeCellValue(bc); } else { - // Our custom UI that is faster for long HTML completion - // lists. + // Our custom UI that is faster for long HTML completion lists. ui = new FastListUI(); setPrototypeCellValue(null); } diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/AutoCompletionEvent.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/AutoCompletionEvent.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/AutoCompletionEvent.java 1970-01-01 00:00:00.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/AutoCompletionEvent.java 2014-06-29 18:45:32.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * 02/08/2014 + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package org.fife.ui.autocomplete; + +import java.util.EventObject; + + +/** + * An event fired by an instance of {@link AutoCompletion}. This can be + * used by applications that wish to be notified of the auto-complete popup + * window showing and hiding. + * + * @author Robert Futrell + * @version 1.0 + */ +public class AutoCompletionEvent extends EventObject { + + /** + * The type of this event. + */ + private Type type; + + + /** + * Constructor. + * + * @param source The AutoCompletion instance that fired + * this event. + * @param type The event type. + */ + public AutoCompletionEvent(AutoCompletion source, Type type) { + super(source); + this.type = type; + } + + + /** + * Returns the source AutoCompletion instance. This is just + * shorthand for return (AutoCompletion)getSource();. + * + * @return The source AutoCompletion instance. + */ + public AutoCompletion getAutoCompletion() { + return (AutoCompletion)getSource(); + } + + + /** + * Returns the type of this event. + * + * @return The type of this event. + */ + public Type getEventType() { + return type; + } + + + /** + * Enumeration of the various types of this event. + */ + public static enum Type { + POPUP_SHOWN, + POPUP_HIDDEN + } + + +} \ No newline at end of file diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/AutoCompletion.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/AutoCompletion.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/AutoCompletion.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/AutoCompletion.java 2014-06-29 18:45:32.000000000 +0000 @@ -2,7 +2,7 @@ * 12/21/2008 * * AutoCompletion.java - Handles auto-completion for a text component. - * + * * This library is distributed under a modified BSD license. See the included * RSyntaxTextArea.License.txt file for details. */ @@ -10,21 +10,18 @@ import java.awt.*; import java.awt.event.*; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; +import java.beans.*; import java.util.List; import javax.swing.*; -import javax.swing.event.CaretEvent; -import javax.swing.event.CaretListener; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; +import javax.swing.Timer; +import javax.swing.event.*; import javax.swing.text.*; /** - * Adds auto-completion to a text component. Provides a popup window with a + * Adds auto-completion to a text component. Provides a popup window with a * list of auto-complete choices on a given keystroke, such as Crtrl+Space.

- * + * * Depending on the {@link CompletionProvider} installed, the following * auto-completion features may be enabled: * @@ -33,20 +30,19 @@ *

  • A "description" window displayed alongside the choices list that * provides documentation on the currently selected completion choice * (as seen in Eclipse and NetBeans).
  • - *
  • Parameter assistance. If this is enabled, if the user enters a - * "parameterized" completion, such as a method or a function, then - * they will receive a tool tip describing the arguments they have to - * enter to the completion. Also, the arguments can be navigated via - * tab and shift+tab (a la Eclipse and NetBeans).
  • + *
  • Parameter assistance. If this is enabled, if the user enters a + * "parameterized" completion, such as a method or a function, then they + * will receive a tool tip describing the arguments they have to enter to + * the completion. Also, the arguments can be navigated via tab and + * shift+tab (a la Eclipse and NetBeans).
  • * - * + * * @author Robert Futrell * @version 1.0 */ -/* - * This class handles intercepting window and hierarchy events from the text - * component, so the popup window is only visible when it should be visible. - * It also handles communication between the CompletionProvider and the actual +/* This class handles intercepting window and hierarchy events from the text + * component, so the popup window is only visible when it should be visible. It + * also handles communication between the CompletionProvider and the actual * popup Window. */ public class AutoCompletion { @@ -67,17 +63,16 @@ private AutoCompletePopupWindow popupWindow; /** - * The preferred size of the completion choices window. This field exists - * because the user will likely set the preferred size of the window - * before it is actually created. + * The preferred size of the completion choices window. This field exists + * because the user will likely set the preferred size of the window before + * it is actually created. */ private Dimension preferredChoicesWindowSize; /** - * The preferred size of the optional description window. This field - * only exists because the user may (and usually will) set the size of - * the description window before it exists (it must be parented to a - * Window). + * The preferred size of the optional description window. This field only + * exists because the user may (and usually will) set the size of the + * description window before it exists (it must be parented to a Window). */ private Dimension preferredDescWindowSize; @@ -92,7 +87,7 @@ private CompletionProvider provider; /** - * The renderer to use for the completion choices. If this is + * The renderer to use for the completion choices. If this is * null, then a default renderer is used. */ private ListCellRenderer renderer; @@ -127,9 +122,9 @@ private boolean autoActivationEnabled; /** - * Whether or not, when there is only a single auto-complete option - * that matches the text at the current text position, that text should - * be auto-inserted, instead of the completion window displaying. + * Whether or not, when there is only a single auto-complete option that + * matches the text at the current text position, that text should be + * auto-inserted, instead of the completion window displaying. */ private boolean autoCompleteSingleChoices; @@ -139,9 +134,9 @@ private boolean parameterAssistanceEnabled; /** - * A renderer used for {@link Completion}s in the optional parameter - * choices popup window (displayed when a {@link ParameterizedCompletion} - * is code-completed). If this isn't set, a default renderer is used. + * A renderer used for {@link Completion}s in the optional parameter choices + * popup window (displayed when a {@link ParameterizedCompletion} is + * code-completed). If this isn't set, a default renderer is used. */ private ListCellRenderer paramChoicesRenderer; @@ -157,8 +152,8 @@ private Object oldTriggerKey; /** - * The action previously assigned to {@link #trigger}, so we can reset it - * if the user disables auto-completion. + * The action previously assigned to {@link #trigger}, so we can reset it if + * the user disables auto-completion. */ private Action oldTriggerAction; @@ -169,39 +164,63 @@ private Object oldParenKey; /** - * The action previously assigned to the parameter completion key, so we - * can reset it when we uninstall. + * The action previously assigned to the parameter completion key, so we can + * reset it when we uninstall. */ private Action oldParenAction; /** - * Listens for events in the parent window that affect the visibility of - * the popup windows. + * Listens for events in the parent window that affect the visibility of the + * popup windows. */ private ParentWindowListener parentWindowListener; /** - * Listens for events from the text component that affect the visibility - * of the popup windows. + * Listens for events from the text component that affect the visibility of + * the popup windows. */ private TextComponentListener textComponentListener; /** - * Listens for events in the text component that cause the popup windows - * to automatically activate. + * Listens for events in the text component that cause the popup windows to + * automatically activate. */ private AutoActivationListener autoActivationListener; /** - * Listens for LAF changes so the auto-complete windows automatically - * update themselves accordingly. + * Listens for LAF changes so the auto-complete windows automatically update + * themselves accordingly. */ private LookAndFeelChangeListener lafListener; /** + * Listens for events from the popup window. + */ + private PopupWindowListener popupWindowListener; + + /** + * All listeners registered on this component. + */ + private EventListenerList listeners; + + /** + * Whether or not the popup should be hidden when user types a space (or any + * character that resets the completion list to "all completions"). Defaults + * to true. + */ + private boolean hideOnNoText; + + /** + * Whether or not the popup should be hidden when the CompletionProvider + * changes. If set to false, caller has to ensure refresh of the popup + * content. Defaults to true. + */ + private boolean hideOnCompletionProviderChange; + + /** * The key used in the input map for the AutoComplete action. */ - private static final String PARAM_TRIGGER_KEY = "AutoComplete"; + private static final String PARAM_TRIGGER_KEY = "AutoComplete"; /** * Key used in the input map for the parameter completion action. @@ -212,8 +231,7 @@ * Stores how to render auto-completion-specific highlights in text * components. */ - private static final AutoCompletionStyleContext styleContext = - new AutoCompletionStyleContext(); + private static final AutoCompletionStyleContext styleContext = new AutoCompletionStyleContext(); /** * Whether debug messages should be printed to stdout as AutoCompletion @@ -224,9 +242,8 @@ /** * Constructor. - * - * @param provider The completion provider. This cannot be - * null. + * + * @param provider The completion provider. This cannot be null */ public AutoCompletion(CompletionProvider provider) { @@ -239,17 +256,32 @@ setAutoCompleteSingleChoices(true); setAutoActivationEnabled(false); setShowDescWindow(false); + setHideOnCompletionProviderChange(true); + setHideOnNoText(true); parentWindowListener = new ParentWindowListener(); textComponentListener = new TextComponentListener(); autoActivationListener = new AutoActivationListener(); lafListener = new LookAndFeelChangeListener(); + popupWindowListener = new PopupWindowListener(); + listeners = new EventListenerList(); + + } + + /** + * Adds a listener interested in popup window events from this instance. + * + * @param l The listener to add. + * @see #removeAutoCompletionListener(AutoCompletionListener) + */ + public void addAutoCompletionListener(AutoCompletionListener l) { + listeners.add(AutoCompletionListener.class, l); } /** - * Displays the popup window. Hosting applications can call this method - * to programmatically begin an auto-completion operation. + * Displays the popup window. Hosting applications can call this method to + * programmatically begin an auto-completion operation. */ public void doCompletion() { refreshPopupWindow(); @@ -257,9 +289,34 @@ /** + * Fires an {@link AutoCompletionEvent} of the specified type. + * + * @param type The type of event to fire. + */ + protected void fireAutoCompletionEvent(AutoCompletionEvent.Type type) { + + // Guaranteed to return a non-null array + Object[] listeners = this.listeners.getListenerList(); + AutoCompletionEvent e = null; + + // Process the listeners last to first, notifying those that are + // interested in this event + for (int i=listeners.length-2; i>=0; i-=2) { + if (listeners[i] == AutoCompletionListener.class) { + if (e==null) { + e = new AutoCompletionEvent(this, type); + } + ((AutoCompletionListener)listeners[i+1]).autoCompleteUpdate(e); + } + } + + } + + + /** * Returns the delay between when the user types a character and when the * code completion popup should automatically appear (if applicable). - * + * * @return The delay, in milliseconds. * @see #setAutoActivationDelay(int) */ @@ -269,9 +326,9 @@ /** - * Returns whether, if a single auto-complete choice is available, it - * should be automatically inserted, without displaying the popup menu. - * + * Returns whether, if a single auto-complete choice is available, it should + * be automatically inserted, without displaying the popup menu. + * * @return Whether to auto-complete single choices. * @see #setAutoCompleteSingleChoices(boolean) */ @@ -282,7 +339,7 @@ /** * Returns the completion provider. - * + * * @return The completion provider. */ public CompletionProvider getCompletionProvider() { @@ -292,7 +349,7 @@ /** * Returns whether debug is enabled for AutoCompletion. - * + * * @return Whether debug is enabled. */ static boolean getDebug() { @@ -301,9 +358,9 @@ /** - * Returns the default auto-complete "trigger key" for this OS. For - * Windows, for example, it is Ctrl+Space. - * + * Returns the default auto-complete "trigger key" for this OS. For Windows, + * for example, it is Ctrl+Space. + * * @return The default auto-complete trigger key. */ public static KeyStroke getDefaultTriggerKey() { @@ -316,7 +373,7 @@ /** * Returns the handler to use when an external URL is clicked in the * description window. - * + * * @return The handler. * @see #setExternalURLHandler(ExternalURLHandler) * @see #getLinkRedirector() @@ -335,7 +392,7 @@ /** * Returns the link redirector, if any. - * + * * @return The link redirector, or null if none. * @see #setLinkRedirector(LinkRedirector) */ @@ -347,7 +404,7 @@ /** * Returns the default list cell renderer used when a completion provider * does not supply its own. - * + * * @return The default list cell renderer. * @see #setListCellRenderer(ListCellRenderer) */ @@ -359,9 +416,9 @@ /** * Returns the renderer to use for {@link Completion}s in the optional * parameter choices popup window (displayed when a - * {@link ParameterizedCompletion} is code-completed). If this returns + * {@link ParameterizedCompletion} is code-completed). If this returns * null, a default renderer is used. - * + * * @return The renderer to use. * @see #setParamChoicesRenderer(ListCellRenderer) * @see #isParameterAssistanceEnabled() @@ -372,12 +429,12 @@ /** - * Returns the text to replace with in the document. This is a - * "last-chance" hook for subclasses to make special modifications to the - * completion text inserted. The default implementation simply returns - * c.getReplacementText(). You usually will not need to modify - * this method. - * + * Returns the text to replace with in the document. This is a "last-chance" + * hook for subclasses to make special modifications to the completion text + * inserted. The default implementation simply returns + * c.getReplacementText(). You usually will not need to modify this + * method. + * * @param c The completion being inserted. * @param doc The document being modified. * @param start The start of the text being replaced. @@ -385,15 +442,15 @@ * @return The text to replace with. */ protected String getReplacementText(Completion c, Document doc, int start, - int len) { + int len) { return c.getReplacementText(); } /** - * Returns whether the "description window" should be shown alongside - * the completion window. - * + * Returns whether the "description window" should be shown alongside the + * completion window. + * * @return Whether the description window should be shown. * @see #setShowDescWindow(boolean) */ @@ -405,7 +462,7 @@ /** * Returns the style context describing how auto-completion related * highlights in the editor are rendered. - * + * * @return The style context. */ public static AutoCompletionStyleContext getStyleContext() { @@ -415,7 +472,7 @@ /** * Returns the text component for which auto-completion is enabled. - * + * * @return The text component, or null if this * {@link AutoCompletion} is not installed on any text component. * @see #install(JTextComponent) @@ -427,19 +484,19 @@ /** * Returns the orientation of the text component we're installed to. - * - * @return The orientation of the text component, or null if - * we are not installed on one. + * + * @return The orientation of the text component, or null if we + * are not installed on one. */ ComponentOrientation getTextComponentOrientation() { - return textComponent==null ? null : - textComponent.getComponentOrientation(); + return textComponent == null ? null : textComponent + .getComponentOrientation(); } /** * Returns the "trigger key" used for auto-complete. - * + * * @return The trigger key. * @see #setTriggerKey(KeyStroke) */ @@ -450,11 +507,11 @@ /** * Hides any child windows being displayed by the auto-completion system. - * + * * @return Whether any windows were visible. */ public boolean hideChildWindows() { - //return hidePopupWindow() || hideToolTipWindow(); + // return hidePopupWindow() || hideToolTipWindow(); boolean res = hidePopupWindow(); res |= hideParameterCompletionPopups(); return res; @@ -463,11 +520,11 @@ /** * Hides and disposes of any parameter completion-related popups. - * + * * @return Whether any such windows were visible (and thus hidden). */ private boolean hideParameterCompletionPopups() { - if (pcc!=null) { + if (pcc != null) { pcc.deactivate(); pcc = null; return true; @@ -478,13 +535,13 @@ /** * Hides the popup window, if it is visible. - * + * * @return Whether the popup window was visible. */ - private boolean hidePopupWindow() { - if (popupWindow!=null) { + protected boolean hidePopupWindow() { + if (popupWindow != null) { if (popupWindow.isVisible()) { - popupWindow.setVisible(false); + setPopupVisible(false); return true; } } @@ -494,9 +551,9 @@ /** * Determines whether debug should be enabled for the AutoCompletion - * library. This method checks a system property, but takes care of + * library. This method checks a system property, but takes care of * {@link SecurityException}s in case we're in an applet or WebStart. - * + * * @return Whether debug should be enabled. */ private static final boolean initDebug() { @@ -511,10 +568,10 @@ /** - * Inserts a completion. Any time a code completion event occurs, the - * actual text insertion happens through this method. - * - * @param c A completion to insert. This cannot be null. + * Inserts a completion. Any time a code completion event occurs, the actual + * text insertion happens through this method. + * + * @param c A completion to insert. This cannot be null. */ protected final void insertCompletion(Completion c) { insertCompletion(c, false); @@ -522,12 +579,12 @@ /** - * Inserts a completion. Any time a code completion event occurs, the - * actual text insertion happens through this method. - * - * @param c A completion to insert. This cannot be null. - * @param typedParamListStartChar Whether the parameterized completion - * start character was typed (typically '('). + * Inserts a completion. Any time a code completion event occurs, the actual + * text insertion happens through this method. + * + * @param c A completion to insert. This cannot be null. + * @param typedParamListStartChar Whether the parameterized completion start + * character was typed (typically '('). */ protected void insertCompletion(Completion c, boolean typedParamListStartChar) { @@ -539,17 +596,17 @@ int dot = caret.getDot(); int len = alreadyEntered.length(); - int start = dot-len; + int start = dot - len; String replacement = getReplacementText(c, textComp.getDocument(), - start, len); + start, len); caret.setDot(start); caret.moveDot(dot); textComp.replaceSelection(replacement); - if (isParameterAssistanceEnabled() && - (c instanceof ParameterizedCompletion)) { - ParameterizedCompletion pc = (ParameterizedCompletion)c; + if (isParameterAssistanceEnabled() + && (c instanceof ParameterizedCompletion)) { + ParameterizedCompletion pc = (ParameterizedCompletion) c; startParameterizedCompletionAssistance(pc, typedParamListStartChar); } @@ -557,16 +614,16 @@ /** - * Installs this auto-completion on a text component. If this + * Installs this auto-completion on a text component. If this * {@link AutoCompletion} is already installed on another text component, * it is uninstalled first. - * + * * @param c The text component. * @see #uninstall() */ public void install(JTextComponent c) { - if (textComponent!=null) { + if (textComponent != null) { uninstall(); } @@ -576,19 +633,19 @@ // Install the function completion key, if there is one. // NOTE: We cannot do this if the start char is ' ' (e.g. just a space // between the function name and parameters) because it overrides - // RSTA's special space action. It seems KeyStorke.getKeyStroke(' ') + // RSTA's special space action. It seems KeyStorke.getKeyStroke(' ') // hoses ctrl+space, shift+space, etc., even though I think it // shouldn't... char start = provider.getParameterListStart(); - if (start!=0 && start!=' ') { + if (start != 0 && start != ' ') { InputMap im = c.getInputMap(); ActionMap am = c.getActionMap(); KeyStroke ks = KeyStroke.getKeyStroke(start); oldParenKey = im.get(ks); im.put(ks, PARAM_COMPLETE_KEY); oldParenAction = am.get(PARAM_COMPLETE_KEY); - am.put(PARAM_COMPLETE_KEY, - new ParameterizedCompletionStartAction(start)); + am.put(PARAM_COMPLETE_KEY, new ParameterizedCompletionStartAction( + start)); } textComponentListener.addTo(this.textComponent); @@ -607,9 +664,9 @@ /** * Installs a "trigger key" action onto the current text component. - * + * * @param ks The keystroke that should trigger the action. - * @see #uninstallTriggerKey() + * @see #uninstallTriggerKey() */ private void installTriggerKey(KeyStroke ks) { InputMap im = textComponent.getInputMap(); @@ -617,16 +674,30 @@ im.put(ks, PARAM_TRIGGER_KEY); ActionMap am = textComponent.getActionMap(); oldTriggerAction = am.get(PARAM_TRIGGER_KEY); - am.put(PARAM_TRIGGER_KEY, new AutoCompleteAction()); + am.put(PARAM_TRIGGER_KEY, createAutoCompleteAction()); + } + + + /** + * Creates and returns the action to call when the user presses the + * auto-completion trigger key (e.g. ctrl+space). This is a hook for + * subclasses that want to provide their own behavior in this scenario. + * The default implementation returns an {@link AutoCompleteAction}. + * + * @return The action to use. + * @see AutoCompleteAction + */ + protected Action createAutoCompleteAction() { + return new AutoCompleteAction(); } /** * Returns whether auto-activation is enabled (that is, whether the * completion popup will automatically appear after a delay when the user - * types an appropriate character). Note that this parameter will be - * ignored if auto-completion is disabled. - * + * types an appropriate character). Note that this parameter will be ignored + * if auto-completion is disabled. + * * @return Whether auto-activation is enabled. * @see #setAutoActivationEnabled(boolean) * @see #getAutoActivationDelay() @@ -639,7 +710,7 @@ /** * Returns whether auto-completion is enabled. - * + * * @return Whether auto-completion is enabled. * @see #setAutoCompleteEnabled(boolean) */ @@ -649,8 +720,31 @@ /** - * Returns whether parameter assistance is enabled. + * Whether or not the popup should be hidden when the CompletionProvider + * changes. If set to false, caller has to ensure refresh of the popup + * content. * + * @see #setHideOnCompletionProviderChange(boolean) + */ + protected boolean isHideOnCompletionProviderChange() { + return hideOnCompletionProviderChange; + } + + + /** + * Whether or not the popup should be hidden when user types a space (or + * any character that resets the completion list to "all completions"). + * + * @see #setHideOnNoText(boolean) + */ + protected boolean isHideOnNoText() { + return hideOnNoText; + } + + + /** + * Returns whether parameter assistance is enabled. + * * @return Whether parameter assistance is enabled. * @see #setParameterAssistanceEnabled(boolean) */ @@ -660,30 +754,30 @@ /** - * Returns whether the popup window is visible. - * - * @return Whether the popup window is visible. + * Returns whether the completion popup window is visible. + * + * @return Whether the completion popup window is visible. */ - private boolean isPopupVisible() { - return popupWindow!=null && popupWindow.isVisible(); + public boolean isPopupVisible() { + return popupWindow != null && popupWindow.isVisible(); } /** - * Refreshes the popup window. First, this method gets the possible - * completions for the current caret position. If there are none, and the - * popup is visible, it is hidden. If there are some completions and the + * Refreshes the popup window. First, this method gets the possible + * completions for the current caret position. If there are none, and the + * popup is visible, it is hidden. If there are some completions and the * popup is hidden, it is made visible and made to display the completions. * If there are some completions and the popup is visible, its list is * updated to the current set of completions. - * + * * @return The current line number of the caret. */ protected int refreshPopupWindow() { // A return value of null => don't suggest completions String text = provider.getAlreadyEnteredText(textComponent); - if (text==null && !isPopupVisible()) { + if (text == null && !isPopupVisible()) { return getLineOfCaret(); } @@ -691,37 +785,38 @@ // character that resets the completion list to "all completions"), // the popup window should be hidden instead of being reset to show // everything. - int textLen = text==null ? 0 : text.length(); - if (textLen==0) { + int textLen = text == null ? 0 : text.length(); + if (textLen == 0 && isHideOnNoText()) { if (isPopupVisible()) { hidePopupWindow(); return getLineOfCaret(); } } - final List completions = provider. - getCompletions(textComponent); - int count = completions.size(); + final List completions = provider + .getCompletions(textComponent); + int count = completions==null ? 0 : completions.size(); - if (count>1 || (count==1 && (isPopupVisible() || textLen==0)) || - (count==1 && !getAutoCompleteSingleChoices())) { + if (count > 1 || (count == 1 && (isPopupVisible() || textLen == 0)) + || (count == 1 && !getAutoCompleteSingleChoices())) { - if (popupWindow==null) { + if (popupWindow == null) { popupWindow = new AutoCompletePopupWindow(parentWindow, this); + popupWindowListener.install(popupWindow); // Completion is usually done for code, which is always done // LTR, so make completion stuff RTL only if text component is // also RTL. - popupWindow.applyComponentOrientation( - getTextComponentOrientation()); - if (renderer!=null) { + popupWindow + .applyComponentOrientation(getTextComponentOrientation()); + if (renderer != null) { popupWindow.setListCellRenderer(renderer); } - if (preferredChoicesWindowSize!=null) { + if (preferredChoicesWindowSize != null) { popupWindow.setSize(preferredChoicesWindowSize); } - if (preferredDescWindowSize!=null) { - popupWindow.setDescriptionWindowSize( - preferredDescWindowSize); + if (preferredDescWindowSize != null) { + popupWindow + .setDescriptionWindowSize(preferredDescWindowSize); } } @@ -730,8 +825,8 @@ if (!popupWindow.isVisible()) { Rectangle r = null; try { - r = textComponent.modelToView(textComponent. - getCaretPosition()); + r = textComponent.modelToView(textComponent + .getCaretPosition()); } catch (BadLocationException ble) { ble.printStackTrace(); return -1; @@ -741,13 +836,14 @@ r.x = p.x; r.y = p.y; popupWindow.setLocationRelativeTo(r); - popupWindow.setVisible(true); + setPopupVisible(true); } } - else if (count==1) { // !isPopupVisible && autoCompleteSingleChoices + else if (count == 1) { // !isPopupVisible && autoCompleteSingleChoices SwingUtilities.invokeLater(new Runnable() { + public void run() { insertCompletion(completions.get(0)); } @@ -764,10 +860,21 @@ /** - * Sets the delay between when the user types a character and when the - * code completion popup should automatically appear (if applicable). + * Removes a listener interested in popup window events from this instance. * - * @param ms The delay, in milliseconds. This should be greater than zero. + * @param l The listener to remove. + * @see #addAutoCompletionListener(AutoCompletionListener) + */ + public void removeAutoCompletionListener(AutoCompletionListener l) { + listeners.remove(AutoCompletionListener.class, l); + } + + + /** + * Sets the delay between when the user types a character and when the code + * completion popup should automatically appear (if applicable). + * + * @param ms The delay, in milliseconds. This should be greater than zero. * @see #getAutoActivationDelay() */ public void setAutoActivationDelay(int ms) { @@ -778,17 +885,17 @@ /** - * Toggles whether auto-activation is enabled. Note that auto-activation + * Toggles whether auto-activation is enabled. Note that auto-activation * also depends on auto-completion itself being enabled. - * + * * @param enabled Whether auto-activation is enabled. * @see #isAutoActivationEnabled() * @see #setAutoActivationDelay(int) */ public void setAutoActivationEnabled(boolean enabled) { - if (enabled!=autoActivationEnabled) { + if (enabled != autoActivationEnabled) { autoActivationEnabled = enabled; - if (textComponent!=null) { + if (textComponent != null) { if (autoActivationEnabled) { autoActivationListener.addTo(textComponent); } @@ -802,12 +909,12 @@ /** * Sets whether auto-completion is enabled. - * + * * @param enabled Whether auto-completion is enabled. * @see #isAutoCompleteEnabled() */ public void setAutoCompleteEnabled(boolean enabled) { - if (enabled!=autoCompleteEnabled) { + if (enabled != autoCompleteEnabled) { autoCompleteEnabled = enabled; hidePopupWindow(); } @@ -815,9 +922,9 @@ /** - * Sets whether, if a single auto-complete choice is available, it should - * be automatically inserted, without displaying the popup menu. - * + * Sets whether, if a single auto-complete choice is available, it should be + * automatically inserted, without displaying the popup menu. + * * @param autoComplete Whether to auto-complete single choices. * @see #getAutoCompleteSingleChoices() */ @@ -828,31 +935,33 @@ /** * Sets the completion provider being used. - * - * @param provider The new completion provider. This cannot be + * + * @param provider The new completion provider. This cannot be * null. * @throws IllegalArgumentException If provider is * null. */ public void setCompletionProvider(CompletionProvider provider) { - if (provider==null) { + if (provider == null) { throw new IllegalArgumentException("provider cannot be null"); } this.provider = provider; - hidePopupWindow(); // In case new choices should be displayed. + if (isHideOnCompletionProviderChange()) { + hidePopupWindow(); // In case new choices should be displayed. + } } /** * Sets the size of the completion choices window. - * + * * @param w The new width. * @param h The new height. * @see #setDescriptionWindowSize(int, int) */ public void setChoicesWindowSize(int w, int h) { preferredChoicesWindowSize = new Dimension(w, h); - if (popupWindow!=null) { + if (popupWindow != null) { popupWindow.setSize(preferredChoicesWindowSize); } } @@ -860,14 +969,14 @@ /** * Sets the size of the description window. - * + * * @param w The new width. * @param h The new height. * @see #setChoicesWindowSize(int, int) */ public void setDescriptionWindowSize(int w, int h) { preferredDescWindowSize = new Dimension(w, h); - if (popupWindow!=null) { + if (popupWindow != null) { popupWindow.setDescriptionWindowSize(preferredDescWindowSize); } } @@ -875,12 +984,12 @@ /** * Sets the handler to use when an external URL is clicked in the - * description window. This handler can perform some action, such as - * open the URL in a web browser. The default implementation will open - * the URL in a browser, but only if running in Java 6. If you want - * browser support for Java 5 and below, or otherwise want to respond to - * hyperlink clicks, you will have to install your own handler to do so. - * + * description window. This handler can perform some action, such as open + * the URL in a web browser. The default implementation will open the URL in + * a browser, but only if running in Java 6. If you want browser support for + * Java 5 and below, or otherwise want to respond to hyperlink clicks, you + * will have to install your own handler to do so. + * * @param handler The new handler. * @see #getExternalURLHandler() */ @@ -890,13 +999,36 @@ /** + * Sets whether or not the popup should be hidden when the + * CompletionProvider changes. If set to false, caller has to ensure refresh + * of the popup content. + * + * @see #isHideOnCompletionProviderChange() + */ + protected void setHideOnCompletionProviderChange( + boolean hideOnCompletionProviderChange) { + this.hideOnCompletionProviderChange = hideOnCompletionProviderChange; + } + + + /** + * Sets whether or not the popup should be hidden when user types a space + * (or any character that resets the completion list to "all completions"). + * + * @see #isHideOnNoText() + */ + protected void setHideOnNoText(boolean hideOnNoText) { + this.hideOnNoText = hideOnNoText; + } + + + /** * Sets the redirector for external URL's found in code completion - * documentation. When a non-local link in completion popups is clicked, + * documentation. When a non-local link in completion popups is clicked, * this redirector is given the chance to modify the URL fetched and * displayed. - * - * @param linkRedirector The link redirector, or null for - * none. + * + * @param linkRedirector The link redirector, or null for none. * @see #getLinkRedirector() */ public static void setLinkRedirector(LinkRedirector linkRedirector) { @@ -907,14 +1039,14 @@ /** * Sets the default list cell renderer to use when a completion provider * does not supply its own. - * - * @param renderer The renderer to use. If this is null, - * a default renderer is used. + * + * @param renderer The renderer to use. If this is null, a + * default renderer is used. * @see #getListCellRenderer() */ public void setListCellRenderer(ListCellRenderer renderer) { this.renderer = renderer; - if (popupWindow!=null) { + if (popupWindow != null) { popupWindow.setListCellRenderer(renderer); hidePopupWindow(); } @@ -924,9 +1056,9 @@ /** * Sets the renderer to use for {@link Completion}s in the optional * parameter choices popup window (displayed when a - * {@link ParameterizedCompletion} is code-completed). If this isn't set, - * a default renderer is used. - * + * {@link ParameterizedCompletion} is code-completed). If this isn't set, a + * default renderer is used. + * * @param r The renderer to use. * @see #getParamChoicesRenderer() * @see #setParameterAssistanceEnabled(boolean) @@ -937,12 +1069,12 @@ /** - * Sets whether parameter assistance is enabled. If parameter assistance - * is enabled, and a "parameterized" completion (such as a function or - * method) is inserted, the user will get "assistance" in inserting the - * parameters in the form of a popup window with documentation and easy - * tabbing through the arguments (as seen in Eclipse and NetBeans). - * + * Sets whether parameter assistance is enabled. If parameter assistance is + * enabled, and a "parameterized" completion (such as a function or method) + * is inserted, the user will get "assistance" in inserting the parameters + * in the form of a popup window with documentation and easy tabbing through + * the arguments (as seen in Eclipse and NetBeans). + * * @param enabled Whether parameter assistance should be enabled. * @see #isParameterAssistanceEnabled() */ @@ -952,9 +1084,23 @@ /** + * Toggles the visibility of the auto-completion popup window. This fires + * an {@link AutoCompletionEvent} of the appropriate type. + * + * @param visible Whether the window should be made visible or hidden. + * @see #isPopupVisible() + */ + protected void setPopupVisible(boolean visible) { + if (visible!=popupWindow.isVisible()) { + popupWindow.setVisible(visible); + } + } + + + /** * Sets whether the "description window" should be shown beside the * completion window. - * + * * @param show Whether to show the description window. * @see #getShowDescWindow() */ @@ -965,19 +1111,19 @@ /** - * Sets the keystroke that should be used to trigger the auto-complete - * popup window. - * + * Sets the keystroke that should be used to trigger the auto-complete popup + * window. + * * @param ks The keystroke. * @throws IllegalArgumentException If ks is null. * @see #getTriggerKey() */ public void setTriggerKey(KeyStroke ks) { - if (ks==null) { + if (ks == null) { throw new IllegalArgumentException("trigger key cannot be null"); } if (!ks.equals(trigger)) { - if (textComponent!=null) { + if (textComponent != null) { // Put old trigger action back. uninstallTriggerKey(); // Grab current action for new trigger and replace it. @@ -990,27 +1136,29 @@ /** * Displays a "tool tip" detailing the inputs to the function just entered. - * + * * @param pc The completion. * @param typedParamListStartChar Whether the parameterized completion list * starting character was typed. */ private void startParameterizedCompletionAssistance( - ParameterizedCompletion pc, boolean typedParamListStartChar) { + ParameterizedCompletion pc, boolean typedParamListStartChar) { // Get rid of the previous tool tip window, if there is one. hideParameterCompletionPopups(); // Don't bother with a tool tip if there are no parameters, but if // they typed e.g. the opening '(', make them overtype the ')'. - if (pc.getParamCount()==0 && !(pc instanceof TemplateCompletion)) { + if (pc.getParamCount() == 0 && !(pc instanceof TemplateCompletion)) { CompletionProvider p = pc.getProvider(); char end = p.getParameterListEnd(); // Might be '\0' - String text = end=='\0' ? "" : Character.toString(end); + String text = end == '\0' ? "" : Character.toString(end); if (typedParamListStartChar) { String template = "${}" + text + "${cursor}"; - textComponent.replaceSelection(Character.toString(p.getParameterListStart())); - TemplateCompletion tc = new TemplateCompletion(p, null, null, template); + textComponent.replaceSelection(Character.toString(p + .getParameterListStart())); + TemplateCompletion tc = new TemplateCompletion(p, null, null, + template); pc = tc; } else { @@ -1027,14 +1175,14 @@ /** - * Uninstalls this auto-completion from its text component. If it is not + * Uninstalls this auto-completion from its text component. If it is not * installed on any text component, nothing happens. - * + * * @see #install(JTextComponent) */ public void uninstall() { - if (textComponent!=null) { + if (textComponent != null) { hidePopupWindow(); // Unregisters listeners, actions, etc. @@ -1042,7 +1190,7 @@ // Uninstall the function completion key. char start = provider.getParameterListStart(); - if (start!=0) { + if (start != 0) { KeyStroke ks = KeyStroke.getKeyStroke(start); InputMap im = textComponent.getInputMap(); im.put(ks, oldParenKey); @@ -1051,7 +1199,7 @@ } textComponentListener.removeFrom(textComponent); - if (parentWindow!=null) { + if (parentWindow != null) { parentWindowListener.removeFrom(parentWindow); } @@ -1062,6 +1210,7 @@ UIManager.removePropertyChangeListener(lafListener); textComponent = null; + popupWindowListener.uninstall(popupWindow); popupWindow = null; } @@ -1070,9 +1219,9 @@ /** - * Replaces the "trigger key" action with the one that was there - * before auto-completion was installed. - * + * Replaces the "trigger key" action with the one that was there before + * auto-completion was installed. + * * @see #installTriggerKey(KeyStroke) */ private void uninstallTriggerKey() { @@ -1084,30 +1233,29 @@ /** - * Updates the LookAndFeel of the popup window. Applications can call - * this method as appropriate if they support changing the LookAndFeel - * at runtime. + * Updates the LookAndFeel of the popup window. Applications can call this + * method as appropriate if they support changing the LookAndFeel at + * runtime. */ private void updateUI() { - if (popupWindow!=null) { + if (popupWindow != null) { popupWindow.updateUI(); } - if (pcc!=null) { + if (pcc != null) { pcc.updateUI(); } // Will practically always be a JComponent (a JLabel) if (paramChoicesRenderer instanceof JComponent) { - ((JComponent)paramChoicesRenderer).updateUI(); + ((JComponent) paramChoicesRenderer).updateUI(); } } - /** * Listens for events in the text component to auto-activate the code * completion popup. */ - private class AutoActivationListener extends FocusAdapter - implements DocumentListener, CaretListener, ActionListener { + private class AutoActivationListener extends FocusAdapter implements + DocumentListener, CaretListener, ActionListener { private Timer timer; private boolean justInserted; @@ -1137,19 +1285,19 @@ } public void changedUpdate(DocumentEvent e) { - // Ignore + // Ignore } @Override public void focusLost(FocusEvent e) { timer.stop(); - //hideChildWindows(); Other listener will do this + // hideChildWindows(); Other listener will do this } public void insertUpdate(DocumentEvent e) { justInserted = false; - if (isAutoCompleteEnabled() && isAutoActivationEnabled() && - e.getLength()==1) { + if (isAutoCompleteEnabled() && isAutoActivationEnabled() + && e.getLength() == 1) { if (provider.isAutoActivateOkay(textComponent)) { timer.restart(); justInserted = true; @@ -1177,25 +1325,23 @@ } - /** - * The Action that displays the popup window if - * auto-completion is enabled. + * The Action that displays the popup window if auto-completion + * is enabled. */ - private class AutoCompleteAction extends AbstractAction { + protected class AutoCompleteAction extends AbstractAction { public void actionPerformed(ActionEvent e) { if (isAutoCompleteEnabled()) { refreshPopupWindow(); } - else if (oldTriggerAction!=null) { + else if (oldTriggerAction != null) { oldTriggerAction.actionPerformed(e); } } } - /** * Listens for LookAndFeel changes and updates the various popup windows * involved in auto-completion accordingly. @@ -1211,15 +1357,14 @@ } - /** - * Action that starts a parameterized completion, e.g. after '(' is - * typed. + * Action that starts a parameterized completion, e.g. after '(' is typed. */ private class ParameterizedCompletionStartAction extends AbstractAction { private String start; + public ParameterizedCompletionStartAction(char ch) { this.start = Character.toString(ch); } @@ -1245,13 +1390,12 @@ } - /** * Listens for events in the parent window of the text component with * auto-completion enabled. */ - private class ParentWindowListener extends ComponentAdapter - implements WindowFocusListener { + private class ParentWindowListener extends ComponentAdapter implements + WindowFocusListener { public void addTo(Window w) { w.addComponentListener(this); @@ -1289,10 +1433,38 @@ /** + * Listens for events from the popup window. + */ + private class PopupWindowListener extends ComponentAdapter { + + @Override + public void componentHidden(ComponentEvent e) { + fireAutoCompletionEvent(AutoCompletionEvent.Type.POPUP_HIDDEN); + } + + @Override + public void componentShown(ComponentEvent e) { + fireAutoCompletionEvent(AutoCompletionEvent.Type.POPUP_SHOWN); + } + + public void install(AutoCompletePopupWindow popupWindow) { + popupWindow.addComponentListener(this); + } + + public void uninstall(AutoCompletePopupWindow popupWindow) { + if (popupWindow!=null) { + popupWindow.removeComponentListener(this); + } + } + + } + + + /** * Listens for events from the text component we're installed on. */ - private class TextComponentListener extends FocusAdapter - implements HierarchyListener { + private class TextComponentListener extends FocusAdapter implements + HierarchyListener { void addTo(JTextComponent tc) { tc.addFocusListener(this); @@ -1300,8 +1472,7 @@ } /** - * Hide the auto-completion windows when the text component loses - * focus. + * Hide the auto-completion windows when the text component loses focus. */ @Override public void focusLost(FocusEvent e) { @@ -1310,23 +1481,23 @@ /** * Called when the component hierarchy for our text component changes. - * When the text component is added to a new {@link Window}, this - * method registers listeners on that Window. - * + * When the text component is added to a new {@link Window}, this method + * registers listeners on that Window. + * * @param e The event. */ public void hierarchyChanged(HierarchyEvent e) { // NOTE: e many be null as we call this method at other times. - //System.out.println("Hierarchy changed! " + e); + // System.out.println("Hierarchy changed! " + e); Window oldParentWindow = parentWindow; parentWindow = SwingUtilities.getWindowAncestor(textComponent); - if (parentWindow!=oldParentWindow) { - if (oldParentWindow!=null) { + if (parentWindow != oldParentWindow) { + if (oldParentWindow != null) { parentWindowListener.removeFrom(oldParentWindow); } - if (parentWindow!=null) { + if (parentWindow != null) { parentWindowListener.addTo(parentWindow); } } diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/AutoCompletionListener.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/AutoCompletionListener.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/AutoCompletionListener.java 1970-01-01 00:00:00.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/AutoCompletionListener.java 2014-06-29 18:45:32.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * 02/08/2014 + * + * This library is distributed under a modified BSD license. See the included + * RSyntaxTextArea.License.txt file for details. + */ +package org.fife.ui.autocomplete; + +import java.util.EventListener; + + +/** + * An interface that allows listening for interesting events from an + * {@link AutoCompletion}. + * + * @author Robert Futrell + * @version 1.0 + */ +public interface AutoCompletionListener extends EventListener { + + + /** + * Callback notified when a change to the AutoCompletion's + * status occurs. + * + * @param e The event. + */ + void autoCompleteUpdate(AutoCompletionEvent e); + + +} \ No newline at end of file diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/CompletionCellRenderer.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/CompletionCellRenderer.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/CompletionCellRenderer.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/CompletionCellRenderer.java 2014-06-29 18:45:32.000000000 +0000 @@ -14,8 +14,13 @@ import java.awt.Font; import java.awt.Graphics; import java.awt.Rectangle; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + import javax.swing.DefaultListCellRenderer; import javax.swing.Icon; +import javax.swing.ImageIcon; import javax.swing.JList; import javax.swing.SwingUtilities; import javax.swing.plaf.basic.BasicHTML; @@ -80,6 +85,11 @@ private String paramColor; /** + * An icon to use when no appropriate icon is found. + */ + private Icon emptyIcon; + + /** * Used in rendering calculations. */ private Rectangle paintTextR; @@ -124,6 +134,18 @@ /** + * Creates the icon to use if no icon is found for a specific completion. + * The default implementation returns a 16x16 empty icon. + * + * @return The icon. + * @see #getEmptyIcon() + */ + protected Icon createEmptyIcon() { + return new EmptyIcon(16); + } + + + /** * Returns a decent "parameter" color based on the current default * foreground color. * @@ -199,6 +221,42 @@ /** + * Returns the icon to use if no icon is found for a specific completion. + * This icon is lazily created if necessary. + * + * @return The icon. + * @see #createEmptyIcon() + */ + protected Icon getEmptyIcon() { + if (emptyIcon==null) { + emptyIcon = createEmptyIcon(); + } + return emptyIcon; + } + + + /** + * Returns an icon. + * + * @param resource The icon to retrieve. This should either be a file, + * or a resource loadable by the current ClassLoader. + * @return The icon. + */ + protected Icon getIcon(String resource) { + URL url = getClass().getResource(resource); + if (url==null) { + File file = new File(resource); + try { + url = file.toURI().toURL(); + } catch (MalformedURLException mue) { + mue.printStackTrace(); // Never happens + } + } + return url!=null ? new ImageIcon(url) : null; + } + + + /** * Returns the renderer. * * @param list The list of choices being rendered. @@ -554,16 +612,30 @@ /** + * Sets the icon to display based off of a completion, falling back to the + * empty icon if the completion has no icon. + * + * @param completion The completion to check. + * @see #setIconWithDefault(Completion, Icon) + */ + protected void setIconWithDefault(Completion completion) { + setIconWithDefault(completion, getEmptyIcon()); + } + + + /** * Sets the icon to display based off of a completion, falling back to a * default icon if the completion has no icon. * * @param completion The completion to check. * @param defaultIcon The icon to use if completion does not * specify an icon. + * @see #setIconWithDefault(Completion) */ protected void setIconWithDefault(Completion completion, Icon defaultIcon) { Icon icon = completion.getIcon(); - setIcon(icon!=null ? icon : defaultIcon); + setIcon(icon!=null ? icon : + (defaultIcon!=null ? defaultIcon : emptyIcon)); } diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/CompletionListModel.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/CompletionListModel.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/CompletionListModel.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/CompletionListModel.java 2014-06-29 18:45:32.000000000 +0000 @@ -77,9 +77,10 @@ */ public void setContents(Collection contents) { clear(); - if (contents.size()>0) { + int count = contents.size(); + if (count>0) { delegate.addAll(contents); - fireIntervalAdded(this, 0, contents.size()); + fireIntervalAdded(this, 0, count-1); // endpoints included (!) } } diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/CompletionProviderBase.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/CompletionProviderBase.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/CompletionProviderBase.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/CompletionProviderBase.java 2014-06-29 18:45:32.000000000 +0000 @@ -101,8 +101,11 @@ List completions = getCompletionsImpl(comp); if (parent!=null) { - completions.addAll(parent.getCompletions(comp)); - Collections.sort(completions); + List parentCompletions = parent.getCompletions(comp); + if (parentCompletions!=null) { + completions.addAll(parentCompletions); + Collections.sort(completions); + } } // NOTE: We can't sort by relevance prior to this; we need to have diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/CompletionProvider.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/CompletionProvider.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/CompletionProvider.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/CompletionProvider.java 2014-06-29 18:45:32.000000000 +0000 @@ -58,7 +58,7 @@ * * @param comp The text component. * @return The list of {@link Completion}s. If no completions are - * available, this may be null. + * available, this method should return an empty list. */ public List getCompletions(JTextComponent comp); diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/DefaultCompletionProvider.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/DefaultCompletionProvider.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/DefaultCompletionProvider.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/DefaultCompletionProvider.java 2014-06-29 18:45:32.000000000 +0000 @@ -249,7 +249,6 @@ * Initializes this completion provider. */ protected void init() { - completions = new ArrayList(); seg = new Segment(); } diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/LanguageAwareCompletionProvider.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/LanguageAwareCompletionProvider.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/LanguageAwareCompletionProvider.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/LanguageAwareCompletionProvider.java 2014-06-29 18:45:32.000000000 +0000 @@ -11,7 +11,6 @@ import java.awt.Point; import java.awt.event.MouseEvent; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.text.JTextComponent; @@ -152,12 +151,11 @@ */ @Override protected List getCompletionsImpl(JTextComponent comp) { - if (!(comp instanceof RSyntaxTextArea)) { - return new ArrayList(0); - } - CompletionProvider provider = getProviderFor(comp); - if (provider!=null) { - return provider.getCompletions(comp); + if (comp instanceof RSyntaxTextArea) { + CompletionProvider provider = getProviderFor(comp); + if (provider!=null) { + return provider.getCompletions(comp); + } } return Collections.emptyList(); } diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/ParameterizedCompletionContext.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/ParameterizedCompletionContext.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/ParameterizedCompletionContext.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/ParameterizedCompletionContext.java 2014-06-29 18:45:32.000000000 +0000 @@ -1107,7 +1107,15 @@ minPos = info.getMinOffset(); maxPos = info.getMaxOffset(); try { - defaultEndOffs = tc.getDocument().createPosition( + Document doc = tc.getDocument(); + if (maxPos.getOffset()==0) { + // Positions at offset 0 don't track document changes, + // so we must manually do this here. This is not a + // common occurrence. + maxPos = doc.createPosition( + info.getTextToInsert().length()); + } + defaultEndOffs = doc.createPosition( info.getDefaultEndOffs()); } catch (BadLocationException ble) { ble.printStackTrace(); // Never happens diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/RoundRobinAutoCompletion.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/RoundRobinAutoCompletion.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/RoundRobinAutoCompletion.java 1970-01-01 00:00:00.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/RoundRobinAutoCompletion.java 2014-06-29 18:45:32.000000000 +0000 @@ -0,0 +1,143 @@ +/* + * 12/02/2013 + * + * Copyright (C) 2013 Robert Futrell + * robert_futrell at users.sourceforge.net + * http://fifesoft.com/rsyntaxtextarea + * + * This library is distributed under a modified BSD license. See the included + * RSTALanguageSupport.License.txt file for details. + */ +package org.fife.ui.autocomplete; + +import java.util.*; +import java.awt.event.*; +import javax.swing.*; + + +/** + * An AutoCompletion that adds the ability to cycle through a set + * of CompletionProviders via the trigger key. This allows the + * application to logically "group together" completions of similar kinds; + * for example, Java code completions vs. template completions.

    + * + * Usage: + *

    + * XPathDynamicCompletionProvider dynamicProvider = new XPathDynamicCompletionProvider();
    + * RoundRobinAutoCompletion ac = new RoundRobinAutoCompletion(dynamicProvider);
    + * XPathCompletionProvider staticProvider = new XPathCompletionProvider();
    + * ac.addCompletionProvider(staticProvider);
    + * ac.setXXX(..);
    + * ...
    + * ac.install(textArea);
    + * 
    + * + * @author mschlegel + */ +public class RoundRobinAutoCompletion extends AutoCompletion { + + /** The List of CompletionProviders to use */ + private List cycle = new ArrayList(); + + + /** + * Constructor. + * + * @param provider A single completion provider. + * @see #addCompletionProvider(CompletionProvider) + */ + public RoundRobinAutoCompletion(CompletionProvider provider) { + + super(provider); + cycle.add(provider); + + // principal requirement for round-robin + setHideOnCompletionProviderChange(false); + // this is required since otherwise, on empty list of completions for + // one of the CompletionProviders, round-robin completion would not + // work + setHideOnNoText(false); + // this is required to prevent single choice of 1st provider to choose + // the completion since the user may want the second provider to be + // chosen. + setAutoCompleteSingleChoices(false); + + } + + + /** + * Adds an additional CompletionProvider to the list to + * cycle through. + * + * @param provider The new completion provider. + */ + public void addCompletionProvider(CompletionProvider provider) { + cycle.add(provider); + } + + + /** + * Moves to the next Provider internally. Needs refresh of the popup window + * to display the changes. + * + * @return true if the next provider was the default one (thus returned to + * the default view). May be used in case you like to hide the + * popup in this case. + */ + public boolean advanceProvider() { + CompletionProvider currentProvider = getCompletionProvider(); + int i = (cycle.indexOf(currentProvider)+1) % cycle.size(); + setCompletionProvider(cycle.get(i)); + return i==0; + } + + + /** + * Overridden to provide our own implementation of the action. + */ + @Override + protected Action createAutoCompleteAction() { + return new CycleAutoCompleteAction(); + } + + + /** + * Resets the cycle to use the default provider on next refresh. + */ + public void resetProvider() { + CompletionProvider currentProvider = getCompletionProvider(); + CompletionProvider defaultProvider = cycle.get(0); + if (currentProvider != defaultProvider) { + setCompletionProvider(defaultProvider); + } + } + + + /** + * An implementation of the auto-complete action that ensures the proper + * CompletionProvider is displayed based on the context in + * which the user presses the trigger key. + */ + private class CycleAutoCompleteAction extends AutoCompleteAction { + + @Override + public void actionPerformed(ActionEvent e) { + if (isAutoCompleteEnabled()) { + if (isPopupVisible()) { + // The popup is already visible, and user pressed the + // trigger-key. In this case, move to next provider. + advanceProvider(); + } + else { + // Be sure to start with the default provider + resetProvider(); + } + } + super.actionPerformed(e); + } + + } + + + // TODO add label "Ctrl-Space for " to the popup window +} \ No newline at end of file diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/ShorthandCompletion.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/ShorthandCompletion.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/ShorthandCompletion.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/ShorthandCompletion.java 2014-06-29 18:45:32.000000000 +0000 @@ -110,7 +110,7 @@ * @see #getReplacementText() */ protected String getSummaryBody() { - return "" + getReplacementText(); + return "" + getReplacementText(); } diff -Nru autocomplete-2.5.0/src/org/fife/ui/autocomplete/TemplateCompletion.java autocomplete-2.5.3/src/org/fife/ui/autocomplete/TemplateCompletion.java --- autocomplete-2.5.0/src/org/fife/ui/autocomplete/TemplateCompletion.java 2013-08-27 01:34:11.000000000 +0000 +++ autocomplete-2.5.3/src/org/fife/ui/autocomplete/TemplateCompletion.java 2014-06-29 18:45:32.000000000 +0000 @@ -293,7 +293,7 @@ case '$': // "$$" => escaped single dollar sign addTemplatePiece(new TemplatePiece.Text( template.substring(lastOffs, offs+1))); - lastOffs = offs += 2; + lastOffs = offs + 2; break; case '{': // "${...}" => variable int closingCurly = template.indexOf('}', offs+2); @@ -307,7 +307,7 @@ else { addTemplatePiece(new TemplatePiece.Param(varName)); } - lastOffs = offs = closingCurly + 1; + lastOffs = closingCurly + 1; } break; } @@ -364,6 +364,17 @@ } + /** + * Sets the short description of this template completion. + * + * @param shortDesc The new short description. + * @see #getShortDescription() + */ + public void setShortDescription(String shortDesc) { + this.shortDescription = shortDesc; + } + + @Override public String toString() { return getDefinitionString();