package org.hdesktop.swingx.prompt; import java.awt.Color; import java.awt.Font; import javax.swing.text.JTextComponent; import org.hdesktop.swingx.JXFormattedTextField; import org.hdesktop.swingx.JXTextArea; import org.hdesktop.swingx.JXTextField; import org.hdesktop.swingx.painter.Painter; import org.hdesktop.swingx.painter.Painters; import org.hdesktop.swingx.plaf.PromptTextUI; import org.hdesktop.swingx.plaf.TextUIWrapper; /** * <p> * Sets prompt text, foreground, background and {@link FocusBehavior} properties * on a JTextComponent by calling * {@link JTextComponent#putClientProperty(Object, Object)}. These properties * are used by {@link PromptTextUI} instances to render the prompt of a text * component. * </p> * * <p> * This class is used by {@link JXTextField}, {@link JXFormattedTextField} and * {@link JXTextArea} to get and set prompt properties. {@link PromptTextUI} * retrieves these properties using PromptSupport. * </p> * * @see JXTextField * @see JXFormattedTextField * @see JXTextArea * @see PromptTextUI * * @author Peter Weishapl <petw@gmx.net> * @author Karl Schaefer */ public final class PromptSupport { /** * The prompt text property. */ public static final String PROMPT = "promptText"; /** * The color of the prompt text property. */ public static final String FOREGROUND = "promptForeground"; /** * The prompt background property. */ public static final String BACKGROUND = "promptBackground"; /** * The prompt background property. */ public static final String BACKGROUND_PAINTER = "promptBackgroundPainter"; /** * The focus behavior property. */ public static final String FOCUS_BEHAVIOR = "focusBehavior"; /** * The font style property, if different from the components font. */ public static final String FONT_STYLE = "promptFontStyle"; /** * <p> * Determines how the {@link JTextComponent} is rendered when focused and no * text is present. * </p> */ public static enum FocusBehavior { /** * Keep the prompt text visible. */ SHOW_PROMPT, /** * Highlight the prompt text as it would be selected. */ HIGHLIGHT_PROMPT, /** * Hide the prompt text. */ HIDE_PROMPT }; private PromptSupport() { //prevent instantiation } /** * <p> * Convenience method to set the <code>promptText</code> and * <code>promptTextColor</code> on a {@link JTextComponent}. * </p> * <p> * If <code>stayOnUIChange</code> is true, The prompt support will stay * installed, even when the text components UI changes. See * {@link #install(JTextComponent, boolean)}. * </p> * * @param promptText * @param promptForeground * @param promptBackground * @param textComponent */ public static void init(String promptText, Color promptForeground, Color promptBackground, final JTextComponent textComponent) { if (promptText != null && promptText.length() > 0) { setPrompt(promptText, textComponent); } if (promptForeground != null) { setForeground(promptForeground, textComponent); } if (promptBackground != null) { setBackground(promptBackground, textComponent); } } /** * Get the {@link FocusBehavior} of <code>textComponent</code>. * * @param textComponent * @return the {@link FocusBehavior} or {@link FocusBehavior#HIDE_PROMPT} if * none is set */ public static FocusBehavior getFocusBehavior(JTextComponent textComponent) { FocusBehavior fb = (FocusBehavior) textComponent.getClientProperty(FOCUS_BEHAVIOR); if (fb == null) { fb = FocusBehavior.HIDE_PROMPT; } return fb; } /** * Sets the {@link FocusBehavior} on <code>textComponent</code> and * repaints the component to reflect the changes, if it is the focus owner. * * @param focusBehavior * @param textComponent */ public static void setFocusBehavior(FocusBehavior focusBehavior, JTextComponent textComponent) { textComponent.putClientProperty(FOCUS_BEHAVIOR, focusBehavior); if (textComponent.isFocusOwner()) { textComponent.repaint(); } } /** * Get the prompt text of <code>textComponent</code>. * * @param textComponent * @return the prompt text */ public static String getPrompt(JTextComponent textComponent) { return (String) textComponent.getClientProperty(PROMPT); } /** * <p> * Sets the prompt text on <code>textComponent</code>. Also sets the * tooltip text to the prompt text if <code>textComponent</code> has no * tooltip text or the current tooltip text is the same as the current * prompt text. * </p> * <p> * Calls {@link #install(JTextComponent)} to ensure that the * <code>textComponent</code>s UI is wrapped by the appropriate * {@link PromptTextUI}. * </p> * * @param promptText * @param textComponent */ public static void setPrompt(String promptText, JTextComponent textComponent) { TextUIWrapper.getDefaultWrapper().install(textComponent, true); // display prompt as tooltip by default if (textComponent.getToolTipText() == null || textComponent.getToolTipText().equals(getPrompt(textComponent))) { textComponent.setToolTipText(promptText); } textComponent.putClientProperty(PROMPT, promptText); textComponent.repaint(); } /** * Get the foreground color of the prompt text. If no color has been set, * the <code>textComponent</code>s disabled text color will be returned. * * @param textComponent * @return the color of the prompt text or * {@link JTextComponent#getDisabledTextColor()} if none is set */ public static Color getForeground(JTextComponent textComponent) { if (textComponent.getClientProperty(FOREGROUND) == null) { return textComponent.getDisabledTextColor(); } return (Color) textComponent.getClientProperty(FOREGROUND); } /** * Sets the foreground color of the prompt on <code>textComponent</code> * and repaints the component to reflect the changes. This color will be * used when no text is present. * * @param promptTextColor * @param textComponent */ public static void setForeground(Color promptTextColor, JTextComponent textComponent) { textComponent.putClientProperty(FOREGROUND, promptTextColor); textComponent.repaint(); } /** * Get the background color of the <code>textComponent</code>, when no * text is present. If no color has been set, the <code>textComponent</code>s * background color color will be returned. * * @param textComponent * @return the the background color of the text component, when no text is * present */ public static Color getBackground(JTextComponent textComponent) { if (textComponent.getClientProperty(BACKGROUND) == null) { return textComponent.getBackground(); } return (Color) textComponent.getClientProperty(BACKGROUND); } /** * <p> * Sets the prompts background color on <code>textComponent</code> and * repaints the component to reflect the changes. This background color will * only be used when no text is present. * </p> * <p> * Calls {@link #install(JTextComponent)} to ensure that the * <code>textComponent</code>s UI is wrapped by the appropriate * {@link PromptTextUI}. * </p> * * @param background * @param textComponent */ public static void setBackground(Color background, JTextComponent textComponent) { TextUIWrapper.getDefaultWrapper().install(textComponent, true); textComponent.putClientProperty(BACKGROUND, background); textComponent.repaint(); } /** * Get the background painter of the <code>textComponent</code>, when no * text is present. If no painter has been set, then {@code null} will be returned. * * @param textComponent * @return the background painter of the text component */ @SuppressWarnings("unchecked") public static <T extends JTextComponent> Painter<? super T> getBackgroundPainter(T textComponent) { Painter<? super T> painter = (Painter<? super T>) textComponent.getClientProperty(BACKGROUND_PAINTER); if (painter == null) { painter = Painters.EMPTY_PAINTER; } return painter; } /** * <p> * Sets the prompts background painter on <code>textComponent</code> and * repaints the component to reflect the changes. This background painter will * only be used when no text is present. * </p> * <p> * Calls {@link #install(JTextComponent)} to ensure that the * <code>textComponent</code>s UI is wrapped by the appropriate * {@link PromptTextUI}. * </p> * * @param background * @param textComponent */ public static <T extends JTextComponent> void setBackgroundPainter(Painter<? super T> background, T textComponent) { TextUIWrapper.getDefaultWrapper().install(textComponent, true); textComponent.putClientProperty(BACKGROUND_PAINTER, background); textComponent.repaint(); } /** * <p> * Set the style of the prompt font, if different from the * <code>textComponent</code>s font. * </p> * <p> * Allowed values are {@link Font#PLAIN}, {@link Font#ITALIC}, * {@link Font#BOLD}, a combination of {@link Font#BOLD} and * {@link Font#ITALIC} or <code>null</code> if the prompt font should be * the same as the <code>textComponent</code>s font. * </p> * * @param fontStyle * @param textComponent */ public static void setFontStyle(Integer fontStyle, JTextComponent textComponent) { textComponent.putClientProperty(FONT_STYLE, fontStyle); textComponent.revalidate(); textComponent.repaint(); } /** * Returns the font style of the prompt text, or <code>null</code> if the * prompt's font style should not differ from the <code>textComponent</code>s * font. * * @param textComponent * @return font style of the prompt text */ public static Integer getFontStyle(JTextComponent textComponent) { return (Integer) textComponent.getClientProperty(FONT_STYLE); } }