001package com.ganteater.ae.desktop.ui;
002
003import java.awt.*;
004import java.awt.event.*;
005import javax.swing.*;
006import javax.swing.border.*;
007import javax.swing.event.*;
008import javax.swing.text.*;
009
010/**
011 *  The TextPrompt class will display a prompt over top of a text component when
012 *  the Document of the text field is empty. The Show property is used to
013 *  determine the visibility of the prompt.
014 *
015 *  The Font and foreground Color of the prompt will default to those properties
016 *  of the parent text component. You are free to change the properties after
017 *  class construction.
018 */
019public class TextPrompt extends JLabel
020        implements FocusListener, DocumentListener
021{
022        public enum Show
023        {
024                ALWAYS,
025                FOCUS_GAINED,
026                FOCUS_LOST;
027        }
028
029        private JTextComponent component;
030        private Document document;
031
032        private Show show;
033        private boolean showPromptOnce;
034        private int focusLost;
035
036        public TextPrompt(String text, JTextComponent component)
037        {
038                this(text, component, Show.ALWAYS);
039        }
040
041        public TextPrompt(String text, JTextComponent component, Show show)
042        {
043                this.component = component;
044                setShow( show );
045                document = component.getDocument();
046
047                setText( text );
048                setFont( component.getFont() );
049                setForeground( component.getForeground() );
050                setBorder( new EmptyBorder(component.getInsets()) );
051                setHorizontalAlignment(JLabel.LEADING);
052
053                component.addFocusListener( this );
054                document.addDocumentListener( this );
055
056                component.setLayout( new BorderLayout() );
057                component.add( this );
058                checkForPrompt();
059        }
060
061        /**
062         *  Convenience method to change the alpha value of the current foreground
063         *  Color to the specifice value.
064         *
065         *  @param alpha value in the range of 0 - 1.0.
066         */
067        public void changeAlpha(float alpha)
068        {
069                changeAlpha( (int)(alpha * 255) );
070        }
071
072        /**
073         *  Convenience method to change the alpha value of the current foreground
074         *  Color to the specifice value.
075         *
076         *  @param alpha value in the range of 0 - 255.
077         */
078        public void changeAlpha(int alpha)
079        {
080                alpha = alpha > 255 ? 255 : alpha < 0 ? 0 : alpha;
081
082                Color foreground = getForeground();
083                int red = foreground.getRed();
084                int green = foreground.getGreen();
085                int blue = foreground.getBlue();
086
087                Color withAlpha = new Color(red, green, blue, alpha);
088                super.setForeground( withAlpha );
089        }
090
091        /**
092         *  Convenience method to change the style of the current Font. The style
093         *  values are found in the Font class. Common values might be:
094         *  Font.BOLD, Font.ITALIC and Font.BOLD + Font.ITALIC.
095         *
096         *  @param style value representing the the new style of the Font.
097         */
098        public void changeStyle(int style)
099        {
100                setFont( getFont().deriveFont( style ) );
101        }
102
103        /**
104         *  Get the Show property
105         *
106         *  @return the Show property.
107         */
108        public Show getShow()
109        {
110                return show;
111        }
112
113        /**
114         *  Set the prompt Show property to control when the promt is shown.
115         *  Valid values are:
116         *
117         *  Show.AWLAYS (default) - always show the prompt
118         *  Show.Focus_GAINED - show the prompt when the component gains focus
119         *      (and hide the prompt when focus is lost)
120         *  Show.Focus_LOST - show the prompt when the component loses focus
121         *      (and hide the prompt when focus is gained)
122         *
123         *  @param show a valid Show enum
124         */
125        public void setShow(Show show)
126        {
127                this.show = show;
128        }
129
130        /**
131         *  Get the showPromptOnce property
132         *
133         *  @return the showPromptOnce property.
134         */
135        public boolean getShowPromptOnce()
136        {
137                return showPromptOnce;
138        }
139
140        /**
141         *  Show the prompt once. Once the component has gained/lost focus
142         *  once, the prompt will not be shown again.
143         *
144         *  @param showPromptOnce  when true the prompt will only be shown once,
145         *                         otherwise it will be shown repeatedly.
146         */
147        public void setShowPromptOnce(boolean showPromptOnce)
148        {
149                this.showPromptOnce = showPromptOnce;
150        }
151
152        /**
153         *      Check whether the prompt should be visible or not. The visibility
154         *  will change on updates to the Document and on focus changes.
155         */
156        private void checkForPrompt()
157        {
158                //  Text has been entered, remove the prompt
159
160                if (document.getLength() > 0)
161                {
162                        setVisible( false );
163                        return;
164                }
165
166                //  Prompt has already been shown once, remove it
167
168                if (showPromptOnce && focusLost > 0)
169                {
170                        setVisible(false);
171                        return;
172                }
173
174                //  Check the Show property and component focus to determine if the
175                //  prompt should be displayed.
176
177        if (component.hasFocus())
178        {
179                if (show == Show.ALWAYS
180                ||  show ==     Show.FOCUS_GAINED)
181                        setVisible( true );
182                else
183                        setVisible( false );
184        }
185        else
186        {
187                if (show == Show.ALWAYS
188                ||  show ==     Show.FOCUS_LOST)
189                        setVisible( true );
190                else
191                        setVisible( false );
192        }
193        }
194
195//  Implement FocusListener
196
197        public void focusGained(FocusEvent e)
198        {
199                checkForPrompt();
200        }
201
202        public void focusLost(FocusEvent e)
203        {
204                focusLost++;
205                checkForPrompt();
206        }
207
208//  Implement DocumentListener
209
210        public void insertUpdate(DocumentEvent e)
211        {
212                checkForPrompt();
213        }
214
215        public void removeUpdate(DocumentEvent e)
216        {
217                checkForPrompt();
218        }
219
220        public void changedUpdate(DocumentEvent e) {}
221}