001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.widgets;
003
004import java.awt.Color;
005
006import javax.swing.UIManager;
007import javax.swing.event.DocumentEvent;
008import javax.swing.event.DocumentListener;
009import javax.swing.text.JTextComponent;
010
011import org.openstreetmap.josm.actions.search.SearchCompiler;
012
013/**
014 * Decorates a text component with an execution to the search compiler. Afterwards, a {@code "filter"} property change
015 * will be fired and the compiled search can be accessed with {@link #getMatch()}.
016 */
017public final class CompileSearchTextDecorator implements DocumentListener {
018
019    private final JTextComponent textComponent;
020    private final String originalToolTipText;
021    private SearchCompiler.Match filter;
022
023    private CompileSearchTextDecorator(JTextComponent textComponent) {
024        this.textComponent = textComponent;
025        this.originalToolTipText = textComponent.getToolTipText();
026        textComponent.getDocument().addDocumentListener(this);
027    }
028
029    /**
030     * Decorates a text component with an execution to the search compiler. Afterwards, a {@code "filter"} property change
031     * will be fired and the compiled search can be accessed with {@link #getMatch()}.
032     * @param f the text component to decorate
033     * @return an instance of the decorator in order to access the compiled search via {@link #getMatch()}
034     */
035    public static CompileSearchTextDecorator decorate(JTextComponent f) {
036        return new CompileSearchTextDecorator(f);
037    }
038
039    private void setFilter() {
040        try {
041            textComponent.setBackground(UIManager.getColor("TextField.background"));
042            textComponent.setToolTipText(originalToolTipText);
043            filter = SearchCompiler.compile(textComponent.getText());
044        } catch (SearchCompiler.ParseError ex) {
045            textComponent.setBackground(new Color(255, 224, 224));
046            textComponent.setToolTipText(ex.getMessage());
047            filter = new SearchCompiler.Always();
048        }
049        textComponent.firePropertyChange("filter", 0, 1);
050    }
051
052    /**
053     * Returns the compiled search
054     * @return the compiled search
055     */
056    public SearchCompiler.Match getMatch() {
057        return filter;
058    }
059
060    @Override
061    public void insertUpdate(DocumentEvent e) {
062        setFilter();
063    }
064
065    @Override
066    public void removeUpdate(DocumentEvent e) {
067        setFilter();
068    }
069
070    @Override
071    public void changedUpdate(DocumentEvent e) {
072        setFilter();
073    }
074}