[autocomplete] 32/143: Adding ActionScript syntax highlighting. Improved performance of auto-completion list cell renderer for huge completion lists. RSTALanguageSupport demo now allows switching of LAF's at runtime.

Benjamin Mesing ben at alioth.debian.org
Sat Oct 19 12:53:12 UTC 2013


This is an automated email from the git hooks/post-receive script.

ben pushed a commit to branch master
in repository autocomplete.

commit a9fd193f3808b1f94aa0432318c6ec239e6d2173
Author: bobbylight <robert at fifesoft.com>
Date:   Wed Apr 28 13:19:13 2010 +0000

    Adding ActionScript syntax highlighting.
    Improved performance of auto-completion list cell renderer for huge completion lists.
    RSTALanguageSupport demo now allows switching of LAF's at runtime.
---
 .../ui/autocomplete/AutoCompletePopupWindow.java   |    9 +-
 src/org/fife/ui/autocomplete/AutoCompletion.java   |   16 +-
 .../ui/autocomplete/CompletionCellRenderer.java    |   38 ++--
 src/org/fife/ui/autocomplete/FastListUI.java       |  200 ++++++++++++++++++++
 4 files changed, 245 insertions(+), 18 deletions(-)

diff --git a/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java b/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java
index a758582..4150edb 100644
--- a/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java
+++ b/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java
@@ -49,6 +49,7 @@ import javax.swing.event.CaretEvent;
 import javax.swing.event.CaretListener;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
+import javax.swing.plaf.ListUI;
 import javax.swing.text.Caret;
 import javax.swing.text.JTextComponent;
 
@@ -140,7 +141,13 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener,
 
 		this.ac = ac;
 		model = new CompletionListModel();
-		list = new JList(model);
+		list = new JList(model) {
+			public void setUI(ListUI ui) {
+				// Keep our special UI, no matter what
+				super.setUI(new FastListUI());
+			}
+		};
+
 		list.setCellRenderer(new DelegatingCellRenderer());
 		list.addListSelectionListener(this);
 		list.addMouseListener(this);
diff --git a/src/org/fife/ui/autocomplete/AutoCompletion.java b/src/org/fife/ui/autocomplete/AutoCompletion.java
index 5a3663c..dd8ae14 100644
--- a/src/org/fife/ui/autocomplete/AutoCompletion.java
+++ b/src/org/fife/ui/autocomplete/AutoCompletion.java
@@ -24,6 +24,8 @@ package org.fife.ui.autocomplete;
 
 import java.awt.*;
 import java.awt.event.*;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.util.List;
 import javax.swing.*;
 import javax.swing.text.*;
@@ -193,12 +195,24 @@ public class AutoCompletion implements HierarchyListener {
 	 *        <code>null</code>.
 	 */
 	public AutoCompletion(CompletionProvider provider) {
+
 		setCompletionProvider(provider);
 		setTriggerKey(getDefaultTriggerKey());
 		setAutoCompleteEnabled(true);
 		setAutoCompleteSingleChoices(true);
 		setShowDescWindow(false);
 		parentWindowListener = new Listener();
+
+		// Automatically update LAF of popup windows on LookAndFeel changes
+		UIManager.addPropertyChangeListener(new PropertyChangeListener() {
+			public void propertyChange(PropertyChangeEvent e) {
+				String name = e.getPropertyName();
+				if (name.equals("lookAndFeel")) {
+					updateUI();
+				}
+			}
+		});
+
 	}
 
 
@@ -913,7 +927,7 @@ try {
 	 * this method as appropriate if they support changing the LookAndFeel
 	 * at runtime.
 	 */
-	public void updateUI() {
+	private void updateUI() {
 		if (popupWindow!=null) {
 			popupWindow.updateUI();
 		}
diff --git a/src/org/fife/ui/autocomplete/CompletionCellRenderer.java b/src/org/fife/ui/autocomplete/CompletionCellRenderer.java
index dea8082..fa255f6 100644
--- a/src/org/fife/ui/autocomplete/CompletionCellRenderer.java
+++ b/src/org/fife/ui/autocomplete/CompletionCellRenderer.java
@@ -48,29 +48,37 @@ import javax.swing.JList;
 public class CompletionCellRenderer extends DefaultListCellRenderer {
 
 	/**
-	 * The alternating background color.
+	 * The alternating background color, or <code>null</code> if alternating
+	 * row colors should not be used.
 	 */
 	private Color altBG;
 
 	/**
-	 * The font to use when rendering items.
+	 * The font to use when rendering items, or <code>null</code> if the
+	 * list's default font should be used.
 	 */
 	private Font font;
 
+	/**
+	 * Keeps the HTML descriptions from "wrapping" in the list, which cuts off
+	 * words.
+	 */
+	private static final String PREFIX = "<html><nobr>";
+
 
 	/**
 	 * Constructor.
 	 */
 	public CompletionCellRenderer() {
-		setDisplayFont(new Font("Monospaced", Font.PLAIN, 12));
-		setAlternateBackground(new Color(240,240,240));
+		//setDisplayFont(new Font("Monospaced", Font.PLAIN, 12));
+		//setAlternateBackground(new Color(0xf4f4f4));
 	}
 
 
 	/**
 	 * Returns the background color to use on alternating lines.
 	 *
-	 * @return The altnernate background color.  If this is <code>null</code>,
+	 * @return The alternate background color.  If this is <code>null</code>,
 	 *         alternating colors are not used.
 	 * @see #setAlternateBackground(Color)
 	 */
@@ -104,7 +112,9 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
 						int index, boolean selected, boolean hasFocus) {
 
 		super.getListCellRendererComponent(list,value,index,selected,hasFocus);
-		setFont(font); // Overrides super's setFont(list.getFont()).
+		if (font!=null) {
+			setFont(font); // Overrides super's setFont(list.getFont()).
+		}
 
 		if (value instanceof FunctionCompletion) {
 			FunctionCompletion fc = (FunctionCompletion)value;
@@ -144,9 +154,8 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
 	protected void prepareForFunctionCompletion(JList list,
 		FunctionCompletion fc, int index, boolean selected, boolean hasFocus) {
 
-		StringBuffer sb = new StringBuffer("<html><b>");
+		StringBuffer sb = new StringBuffer(PREFIX);
 		sb.append(fc.getName());
-		sb.append("</b>");
 
 		sb.append(fc.getProvider().getParameterListStart());
 		int paramCount = fc.getParamCount();
@@ -176,7 +185,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
 		sb.append(fc.getProvider().getParameterListEnd());
 		sb.append(" : ");
 		if (!selected) {
-			sb.append("<font color='#a0a0ff'>");
+			sb.append("<font color='#808080'>");
 		}
 		sb.append(fc.getType());
 		if (!selected) {
@@ -200,9 +209,8 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
 	protected void prepareForMarkupTagCompletion(JList list,
 		MarkupTagCompletion mc, int index, boolean selected, boolean hasFocus) {
 
-		StringBuffer sb = new StringBuffer("<html><b>");
+		StringBuffer sb = new StringBuffer(PREFIX);
 		sb.append(mc.getName());
-		sb.append("</b>");
 
 		setText(sb.toString());
 
@@ -222,9 +230,8 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
 	protected void prepareForOtherCompletion(JList list,
 		Completion c, int index, boolean selected, boolean hasFocus) {
 
-		StringBuffer sb = new StringBuffer("<html><b>");
+		StringBuffer sb = new StringBuffer(PREFIX);
 		sb.append(c.getInputText());
-		sb.append("</b>");
 
 		setText(sb.toString());
 
@@ -243,14 +250,13 @@ public class CompletionCellRenderer extends DefaultListCellRenderer {
 	protected void prepareForVariableCompletion(JList list,
 		VariableCompletion vc, int index, boolean selected, boolean hasFocus) {
 
-		StringBuffer sb = new StringBuffer("<html><b>");
+		StringBuffer sb = new StringBuffer(PREFIX);
 		sb.append(vc.getName());
-		sb.append("</b>");
 
 		if (vc.getType()!=null) {
 			sb.append(" : ");
 			if (!selected) {
-				sb.append("<font color='#a0a0ff'>");
+				sb.append("<font color='#808080'>");
 			}
 			sb.append(vc.getType());
 			if (!selected) {
diff --git a/src/org/fife/ui/autocomplete/FastListUI.java b/src/org/fife/ui/autocomplete/FastListUI.java
new file mode 100644
index 0000000..14d6a80
--- /dev/null
+++ b/src/org/fife/ui/autocomplete/FastListUI.java
@@ -0,0 +1,200 @@
+/*
+ * 04/26/2010
+ *
+ * FastListUI.java - A JList UI implementation that computes the preferred size
+ * of all cells really fast, to facilitate lists of possibly thousands of items
+ * rendered with HTML, which is slow with BasicListUI extensions.
+ * Copyright (C) 2010 Robert Futrell
+ * robert_futrell at users.sourceforge.net
+ * http://fifesoft.com/rsyntaxtextarea
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA.
+ */
+package org.fife.ui.autocomplete;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.SystemColor;
+import javax.swing.JViewport;
+import javax.swing.ListCellRenderer;
+import javax.swing.ListModel;
+import javax.swing.UIManager;
+import javax.swing.plaf.basic.BasicListUI;
+
+
+/**
+ * A custom list UI, used by the completion choices list.  If the number of
+ * completion choices is "large," it does a fast estimate of the preferred
+ * width and height of list items.  This allows HTML renderers to be used (such
+ * as {@link CompletionCellRenderer}), with thousands of completion choices,
+ * with no performance penalty.  With standard BasicListUI subclasses, this can
+ * cause very poor performance <b>each time</b> the list is displayed, which
+ * is bad for lists that are repeatedly hidden and re-displayed, such as
+ * completion choices.  This is all becasue the calculation to get the
+ * preferred size of each list item, when it is displayed with HTML, is slow.
+ *
+ * @author Robert Futrell
+ * @version 1.0
+ */
+class FastListUI extends BasicListUI {
+
+	/**
+	 * Whether the selection background was overridden (usually because of
+	 * Nimbus) so we know to manually uninstall the color we installed.
+	 */
+	private boolean overriddenBackground;
+
+	/**
+	 * Whether the selection foreground was overridden (usually because of
+	 * Nimbus) so we know to manually uninstall the color we installed.
+	 */
+	private boolean overriddenForeground;
+
+	/**
+	 * If there are more than this many completions in a single list, this
+	 * UI will estimate the cell width and height needed for each item instead
+	 * of computing it, for performance reasons.
+	 */
+	private static final int ESTIMATION_THRESHOLD		= 200;
+
+
+	private Color determineSelectionBackground() {
+		Color c = UIManager.getColor("List.selectionBackground");
+		if (c==null) {
+			c = UIManager.getColor("nimbusSelectionBackground");
+			if (c==null) { // Not Nimbus, but still need a value - fallback
+				c = UIManager.getColor("textHighlight");
+				if (c==null) {
+					c = SystemColor.textHighlight;
+				}
+			}
+		}
+
+		// Nimbus unfortunately requires a Color, not a ColorUIResource, for
+		// the background override to work. This causes this color to "stick"
+		// even if the LAF is changed to something else later.  "c" here may
+		// actually be a ColorUIResource
+		return new Color(c.getRGB());//new ColorUIResource(c);
+
+	}
+
+
+	private Color determineSelectionForeground() {
+		Color c = UIManager.getColor("List.selectionForeground");
+		if (c==null) {
+			c = UIManager.getColor("nimbusSelectedText");
+			if (c==null) { // Not Nimbus, but still need a value - fallback
+				c = UIManager.getColor("textHighlightText");
+				if (c==null) {
+					c = SystemColor.textHighlightText;
+				}
+			}
+		}
+		// Nimbus unfortunately requires Color, not ColorUIResource, and "c"
+		// may actually be a ColorUIResource
+		return new Color(c.getRGB());
+	}
+
+
+	/**
+	 * Overridden to ensure we have selection background/foreground colors
+	 * defined, even if we're in some weirdo LAF such as Nimbus which doesn't
+	 * define them.  Since FastListUI extends BasicListUI, we need these values
+	 * to be defined.
+	 */
+	protected void installDefaults() {
+
+		super.installDefaults();
+
+		if (list.getSelectionBackground()==null) {
+			list.setSelectionBackground(determineSelectionBackground());
+			overriddenBackground = true;
+		}
+
+		if (list.getSelectionForeground()==null) {
+			list.setSelectionForeground(determineSelectionForeground());
+			overriddenForeground = true;
+		}
+	}
+
+
+	/**
+	 * Overridden to work around a Nimbus issue.
+	 */
+	protected void uninstallDefaults() {
+
+		super.uninstallDefaults();
+
+		if (overriddenBackground) {
+			list.setSelectionBackground(null);
+		}
+
+		if (overriddenForeground) {
+			list.setSelectionForeground(null);
+		}
+
+	}
+
+
+	/**
+	 * Recalculates the cell width and height of each cell in the list.  This
+	 * method is overridden to do a fast estimation if the completion list is
+	 * too long, to improve performance for lists with huge amounts of
+	 * completions.
+	 */
+	protected void updateLayoutState() {
+
+		ListModel model = list.getModel();
+		int itemCount = model.getSize();
+
+		// If the item count is small enough to run fast on practically all
+		// machines, go ahead and use the super implementation to determine
+		// the optimal cell sizes.
+		if (itemCount<ESTIMATION_THRESHOLD) {
+			super.updateLayoutState();
+			return;
+		}
+
+		// Otherwise, assume all cells are the same height as the first cell,
+		// and estimate the necessary width.
+
+		ListCellRenderer renderer = list.getCellRenderer();
+
+		cellWidth = list.getWidth();
+		if (list.getParent() instanceof JViewport) { // Always true for us
+			cellWidth = list.getParent().getWidth();
+		}
+		System.out.println(cellWidth);
+
+		// We're getting a fixed cell height for all cells
+		cellHeights = null;
+
+		if (renderer!=null && itemCount>0) {
+			Object value = model.getElementAt(0);
+			java.awt.Component c = renderer.getListCellRendererComponent(list,
+												value, 0, false, false);
+			rendererPane.add(c);
+			Dimension cellSize = c.getPreferredSize();
+			cellHeight = cellSize.height;
+			cellWidth = Math.max(cellWidth, cellSize.width);
+		}
+		else {
+			cellHeight = 20; 
+		}
+
+	}
+
+
+}
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/autocomplete.git



More information about the pkg-java-commits mailing list