GhostText.java
package org.opentrafficsim.swing.gui;
import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;
/**
* Code taken from stack overflow.
* <p>
* Copyright (c) 2024-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
* BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
* </p>
* @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
* @see <a href=
* "https://stackoverflow.com/questions/10506789/how-to-display-faint-gray-ghost-text-in-a-jtextfield">stackoverflow</a>
*/
public class GhostText implements FocusListener, DocumentListener, PropertyChangeListener
{
/** Text component. */
private final JTextComponent textComp;
/** Whether its empty. */
private boolean isEmpty;
/** Ghost color. */
private Color ghostColor;
/** Regular color. */
private Color foregroundColor;
/** Ghost text. */
private final String ghostText;
/**
* Constructor.
* @param textComp text component to receive ghost text.
* @param ghostText ghost text.
*/
public GhostText(final JTextComponent textComp, final String ghostText)
{
this.textComp = textComp;
this.ghostText = ghostText;
this.ghostColor = Color.LIGHT_GRAY;
textComp.addFocusListener(this);
registerListeners();
updateState();
if (!this.textComp.hasFocus())
{
focusLost(null);
}
}
/**
* Delete ghost text.
*/
public void delete()
{
unregisterListeners();
this.textComp.removeFocusListener(this);
}
/**
* Register listeners.
*/
private void registerListeners()
{
this.textComp.getDocument().addDocumentListener(this);
this.textComp.addPropertyChangeListener("foreground", this);
}
/**
* Unregister listeners.
*/
private void unregisterListeners()
{
this.textComp.getDocument().removeDocumentListener(this);
this.textComp.removePropertyChangeListener("foreground", this);
}
/**
* Get ghost color.
* @return ghost color.
*/
public Color getGhostColor()
{
return this.ghostColor;
}
/**
* Set ghost color.
* @param ghostColor ghost color.
*/
public void setGhostColor(final Color ghostColor)
{
this.ghostColor = ghostColor;
}
/**
* Update state.
*/
private void updateState()
{
this.isEmpty = this.textComp.getText().length() == 0;
this.foregroundColor = this.textComp.getForeground();
}
@Override
public void focusGained(final FocusEvent e)
{
if (this.isEmpty)
{
unregisterListeners();
try
{
this.textComp.setText("");
this.textComp.setForeground(this.foregroundColor);
}
finally
{
registerListeners();
}
}
}
@Override
public void focusLost(final FocusEvent e)
{
if (this.isEmpty)
{
unregisterListeners();
try
{
this.textComp.setText(this.ghostText);
this.textComp.setForeground(this.ghostColor);
}
finally
{
registerListeners();
}
}
}
@Override
public void propertyChange(final PropertyChangeEvent evt)
{
updateState();
}
@Override
public void changedUpdate(final DocumentEvent e)
{
updateState();
}
@Override
public void insertUpdate(final DocumentEvent e)
{
updateState();
}
@Override
public void removeUpdate(final DocumentEvent e)
{
updateState();
}
}