This is an automated email from the git hooks/post-receive script. ben pushed a commit to branch master in repository autocomplete.
commit 1f665e5c2d4dc68407d5b8944690170876b9c803 Author: bobbylight <[email protected]> Date: Sun Jan 20 07:30:01 2013 +0000 Adding support for using fancy smancy Substance renderers if a Substance Look and Feel is installed. We don't want a compile time dependency so everything is done by reflection and delegation. This means we don't get Substance's rollover effects, but that's a minor issue. --- .../ui/autocomplete/AutoCompletePopupWindow.java | 49 +++++- .../ui/autocomplete/CompletionCellRenderer.java | 161 ++++++++++++++++++-- src/org/fife/ui/autocomplete/TipUtil.java | 8 + src/org/fife/ui/autocomplete/Util.java | 83 ++++++++++ 4 files changed, 285 insertions(+), 16 deletions(-) diff --git a/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java b/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java index 4d22903..0956704 100644 --- a/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java +++ b/src/org/fife/ui/autocomplete/AutoCompletePopupWindow.java @@ -123,6 +123,12 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, */ private static final int VERTICAL_SPACE = 1; + /** + * The class name of the Substance List UI. + */ + private static final String SUBSTANCE_LIST_UI = + "org.pushingpixels.substance.internal.ui.SubstanceListUI"; + /** * Constructor. @@ -130,19 +136,14 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, * @param parent The parent window (hosting the text component). * @param ac The auto-completion instance. */ - public AutoCompletePopupWindow(Window parent, AutoCompletion ac) { + public AutoCompletePopupWindow(Window parent, final AutoCompletion ac) { super(parent); ComponentOrientation o = ac.getTextComponentOrientation(); this.ac = ac; model = new CompletionListModel(); - list = new JList(model) { - public void setUI(ListUI ui) { - // Keep our special UI, no matter what - super.setUI(new FastListUI()); - } - }; + list = new PopupList(model); list.setCellRenderer(new DelegatingCellRenderer()); list.addListSelectionListener(this); @@ -920,6 +921,40 @@ class AutoCompletePopupWindow extends JWindow implements CaretListener, } + /** + * The actual list of completion choices in this popup window. + */ + private class PopupList extends JList { + + public PopupList(CompletionListModel model) { + super(model); + } + + public void setUI(ListUI ui) { + if (Util.getUseSubstanceRenderers() && + SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) { + // Substance requires its special ListUI be installed for + // its renderers to actually render (!), but long completion + // lists (e.g. PHPCompletionProvider in RSTALanguageSupport) + // will simply populate too slowly on initial display (when + // calculating preferred size of all items), so in this case + // we give a prototype cell value. + CompletionProvider p = ac.getCompletionProvider(); + BasicCompletion bc = new BasicCompletion(p, "Hello world"); + setPrototypeCellValue(bc); + } + else { + // Our custom UI that is faster for long HTML completion + // lists. + ui = new FastListUI(); + setPrototypeCellValue(null); + } + super.setUI(ui); + } + + } + + class RightAction extends AbstractAction { public void actionPerformed(ActionEvent e) { diff --git a/src/org/fife/ui/autocomplete/CompletionCellRenderer.java b/src/org/fife/ui/autocomplete/CompletionCellRenderer.java index 5a82a25..af6365a 100644 --- a/src/org/fife/ui/autocomplete/CompletionCellRenderer.java +++ b/src/org/fife/ui/autocomplete/CompletionCellRenderer.java @@ -17,6 +17,7 @@ import java.awt.Rectangle; import javax.swing.DefaultListCellRenderer; import javax.swing.Icon; import javax.swing.JList; +import javax.swing.SwingUtilities; import javax.swing.plaf.basic.BasicHTML; import javax.swing.text.View; @@ -58,6 +59,11 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { private boolean showTypes; /** + * The color to use when rendering types in completion text. + */ + private String typeColor; + + /** * During rendering, whether the item being rendered is selected. */ private boolean selected; @@ -79,6 +85,14 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { private Rectangle paintTextR; /** + * An optional delegate renderer (primarily for Substance). + */ + private DefaultListCellRenderer delegate; + + private static final String SUBSTANCE_RENDERER_CLASS_NAME = + "org.pushingpixels.substance.api.renderers.SubstanceDefaultListCellRenderer"; + + /** * Keeps the HTML descriptions from "wrapping" in the list, which cuts off * words. */ @@ -89,10 +103,63 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { * Constructor. */ public CompletionCellRenderer() { - //setDisplayFont(new Font("Monospaced", Font.PLAIN, 12)); - setShowTypes(true); - paramColor = "#aa0077"; - paintTextR = new Rectangle(); + init(); + } + + + /** + * Constructor. This is primarily a hook for Substance, or any other + * Look and Feel whose renderers look drastically different than standard + * <code>DefaultListCellRenderer</code>s. Everything except for the text + * rendering will be done by the delegate. In almost all scenarios, you + * will want to use the no-argument constructor instead of this one. + * + * @param delegate The delegate renderer. + * @see #delegateToSubstanceRenderer() + */ + public CompletionCellRenderer(DefaultListCellRenderer delegate) { + setDelegateRenderer(delegate); + init(); + } + + + /** + * Returns a decent "parameter" color based on the current default + * foreground color. + * + * @return The parameter color to use. + */ + private String createParamColor() { + return Util.isLightForeground(getForeground()) ? + Util.getHexString(Util.getHyperlinkForeground()): "#aa0077"; + } + + + /** + * Returns a decent "type" color based on the current default foreground + * color. + * + * @return The type color to use. + */ + private String createTypeColor() { + return "#808080"; + } + + + /** + * Attempts to delegate rendering to a Substance cell renderer. This + * should only be called if Substance is known to be on the classpath. + * + * @throws Exception If Substance is not on the classpath, or some other + * error occurs creating the Substance cell renderer. + * @see Util#getUseSubstanceRenderers() + * @see #setDelegateRenderer(DefaultListCellRenderer) + */ + public void delegateToSubstanceRenderer() throws Exception { + Class clazz = Class.forName(SUBSTANCE_RENDERER_CLASS_NAME); + DefaultListCellRenderer delegate = + (DefaultListCellRenderer)clazz.newInstance(); + setDelegateRenderer(delegate); } @@ -109,6 +176,17 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { /** + * Returns the delegate renderer, or <code>null</code> if there is none. + * + * @return The delegate renderer. + * @see #setDelegateRenderer(DefaultListCellRenderer) + */ + public DefaultListCellRenderer getDelegateRenderer() { + return delegate; + } + + + /** * Returns the font used when rendering completions. * * @return The font. If this is <code>null</code>, then the default list @@ -137,7 +215,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { setFont(font); // Overrides super's setFont(list.getFont()). } this.selected = selected; - this.realBG = altBG!=null && (index&1)==0 ? altBG : list.getBackground(); + this.realBG = altBG!=null && (index&1)==1 ? altBG : list.getBackground(); Completion c = (Completion)value; setIcon(c.getIcon()); @@ -162,7 +240,17 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { prepareForOtherCompletion(list, c, index, selected, hasFocus); } - if (!selected && (index&1)==0 && altBG!=null) { + // A delegate renderer might do its own alternate row striping + // (Substance does). + if (delegate!=null) { + delegate.getListCellRendererComponent(list, getText(), index, + selected, hasFocus); + delegate.setFont(getFont()); + delegate.setIcon(getIcon()); + return delegate; + } + + if (!selected && (index&1)==1 && altBG!=null) { setBackground(altBG); } @@ -183,6 +271,15 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { } + private void init() { + //setDisplayFont(new Font("Monospaced", Font.PLAIN, 12)); + setShowTypes(true); + typeColor = createTypeColor(); + paramColor = createParamColor(); + paintTextR = new Rectangle(); + } + + protected void paintComponent(Graphics g) { //super.paintComponent(g); @@ -282,7 +379,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { if (getShowTypes() && fc.getType()!=null) { sb.append(" : "); if (!selected) { - sb.append("<font color='#808080'>"); + sb.append("<font color='").append(typeColor).append("'>"); } sb.append(fc.getType()); if (!selected) { @@ -355,7 +452,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { if (definition!=null) { sb.append(" - "); if (!selected) { - sb.append("<font color='#808080'>"); + sb.append("<font color='").append(typeColor).append("'>"); } sb.append(definition); if (!selected) { @@ -386,7 +483,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { if (getShowTypes() && vc.getType()!=null) { sb.append(" : "); if (!selected) { - sb.append("<font color='#808080'>"); + sb.append("<font color='").append(typeColor).append("'>"); } sb.append(vc.getType()); if (!selected) { @@ -413,6 +510,22 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { /** + * Sets the delegate renderer. Most users will never use this method; it + * is primarily a hook for Substance and other Look and Feels whose + * renderers look drastically different from the standard + * <code>DefaultListCellRenderer</code>. + * + * @param delegate The new delegate renderer. If this is <code>null</code>, + * the default rendering of this component is used. + * @see #getDelegateRenderer() + * @see #delegateToSubstanceRenderer() + */ + public void setDelegateRenderer(DefaultListCellRenderer delegate) { + this.delegate = delegate; + } + + + /** * Sets the font to use when rendering completion items. * * @param font The font to use. If this is <code>null</code>, then @@ -442,6 +555,7 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { * Sets the color to use for function arguments. * * @param color The color to use. This is ignored if <code>null</code>. + * @see #setTypeColor(Color) */ public void setParamColor(Color color) { if (color!=null) { @@ -462,4 +576,33 @@ public class CompletionCellRenderer extends DefaultListCellRenderer { } + /** + * Sets the color to use for function/field types. Note that if + * {@link #getShowTypes()} returns <code>false</code>, this property + * effectively does nothing. + * + * @param color The color to use for types. This is ignored if + * <code>null</code>. + * @see #setShowTypes(boolean) + * @see #setParamColor(Color) + */ + public void setTypeColor(Color color) { + if (color!=null) { + typeColor = Util.getHexString(color); + } + } + + + /** + * Overridden to update our delegate, if necessary. + */ + public void updateUI() { + super.updateUI(); + if (delegate!=null) { + SwingUtilities.updateComponentTreeUI(delegate); + } + paramColor = createParamColor(); + } + + } \ No newline at end of file diff --git a/src/org/fife/ui/autocomplete/TipUtil.java b/src/org/fife/ui/autocomplete/TipUtil.java index 2caa0d4..7ee8664 100644 --- a/src/org/fife/ui/autocomplete/TipUtil.java +++ b/src/org/fife/ui/autocomplete/TipUtil.java @@ -159,6 +159,14 @@ class TipUtil { "body { font-family: " + font.getFamily() + "; font-size: " + font.getSize() + "pt" + "; color: " + Util.getHexString(fg) + "; }"); + + // Always add link foreground rule. Unfortunately these CSS rules + // stack each time the LaF is changed (how can we overwrite them + // without clearing out the important "standard" ones?). + Color linkFG = Util.getHyperlinkForeground(); + doc.getStyleSheet().addRule( + "a { color: " + Util.getHexString(linkFG) + "; }"); + URL url = TipUtil.class.getResource("bullet_black.png"); if (url!=null) { doc.getStyleSheet().addRule( diff --git a/src/org/fife/ui/autocomplete/Util.java b/src/org/fife/ui/autocomplete/Util.java index ceab7f5..c994b60 100644 --- a/src/org/fife/ui/autocomplete/Util.java +++ b/src/org/fife/ui/autocomplete/Util.java @@ -16,6 +16,8 @@ import java.awt.Rectangle; import java.lang.reflect.Method; import java.net.URI; import java.security.AccessControlException; +import javax.swing.JLabel; +import javax.swing.UIManager; import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; @@ -29,6 +31,19 @@ import org.fife.ui.rsyntaxtextarea.PopupWindowDecorator; public class Util { /** + * If a system property is defined with this name and set, ignoring case, + * to <code>true</code>, this library will not attempt to use Substance + * renderers. Otherwise, if a Substance Look and Feel is installed, we + * will attempt to use Substance cell renderers in all of our dropdowns.<p> + * + * Note that we do not have a build dependency on Substance, so all access + * to Substance stuff is done via reflection. We will fall back onto + * default renderers if something goes horribly wrong. + */ + public static final String PROPERTY_DONT_USE_SUBSTANCE_RENDERERS = + "org.fife.ui.autocomplete.DontUseSubstanceRenderers"; + + /** * If this system property is <code>true</code>, then even the "main" two * auto-complete windows will allow window decorations via * {@link PopupWindowDecorator}. If this property is undefined or @@ -39,6 +54,13 @@ public class Util { public static final String PROPERTY_ALLOW_DECORATED_AUTOCOMPLETE_WINDOWS = "org.fife.ui.autocomplete.allowDecoratedAutoCompleteWindows"; + /** + * Used for the color of hyperlinks when a LookAndFeel uses light text + * against a dark background. + */ + private static final Color LIGHT_HYPERLINK_FG = new Color(0xd8ffff); + + private static final boolean useSubstanceRenderers; private static boolean desktopCreationAttempted; private static Object desktop; private static final Object LOCK_DESKTOP_CREATION = new Object(); @@ -158,6 +180,28 @@ public class Util { /** + * Returns the color to use for hyperlink-style components. This method + * will return <code>Color.blue</code> unless it appears that the current + * LookAndFeel uses light text on a dark background, in which case a + * brighter alternative is returned. + * + * @return The color to use for hyperlinks. + */ + static final Color getHyperlinkForeground() { + + // This property is defined by all standard LaFs, even Nimbus (!), + // but you never know what crazy LaFs there are... + Color fg = UIManager.getColor("Label.foreground"); + if (fg==null) { + fg = new JLabel().getForeground(); + } + + return isLightForeground(fg) ? LIGHT_HYPERLINK_FG : Color.blue; + + } + + + /** * Returns the screen coordinates for the monitor that contains the * specified point. This is useful for setups with multiple monitors, * to ensure that popup windows are positioned properly. @@ -202,6 +246,32 @@ public class Util { /** + * Returns whether we should attempt to use Substance cell renderers and + * styles for things such as completion choices, if a Substance Look and + * Feel is installed. If this is <code>false</code>, we'll use our + * standard rendering for completions, even when Substance is being used. + * + * @return Whether to use Substance renderers if Substance is installed. + */ + public static boolean getUseSubstanceRenderers() { + return useSubstanceRenderers; + } + + + /** + * Returns whether the specified color is "light" to use as a foreground. + * Colors that return <code>true</code> indicate that the current Look and + * Feel probably uses light text colors on a dark background. + * + * @param fg The foreground color. + * @return Whether it is a "light" foreground color. + */ + public static final boolean isLightForeground(Color fg) { + return fg.getRed()>0xa0 && fg.getGreen()>0xa0 && fg.getBlue()>0xa0; + } + + + /** * Returns whether <code>str</code> starts with <code>start</code>, * ignoring case. * @@ -226,4 +296,17 @@ public class Util { } + static { + + boolean use = true; + try { + use = !Boolean.getBoolean(PROPERTY_DONT_USE_SUBSTANCE_RENDERERS); + } catch (AccessControlException ace) { // We're in an applet. + use = true; + } + useSubstanceRenderers = use; + + } + + } \ No newline at end of file -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/autocomplete.git _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

