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.data.osm.search.SearchCompiler;
012import org.openstreetmap.josm.data.osm.search.SearchParseError;
013import org.openstreetmap.josm.tools.Logging;
014
015/**
016 * Decorates a text component with an execution to the search compiler. Afterwards, a {@code "filter"} property change
017 * will be fired and the compiled search can be accessed with {@link #getMatch()}.
018 */
019public final class CompileSearchTextDecorator implements DocumentListener {
020
021    private final JTextComponent textComponent;
022    private final String originalToolTipText;
023    private SearchCompiler.Match filter;
024
025    private CompileSearchTextDecorator(JTextComponent textComponent) {
026        this.textComponent = textComponent;
027        this.originalToolTipText = textComponent.getToolTipText();
028        textComponent.getDocument().addDocumentListener(this);
029    }
030
031    /**
032     * Decorates a text component with an execution to the search compiler. Afterwards, a {@code "filter"} property change
033     * will be fired and the compiled search can be accessed with {@link #getMatch()}.
034     * @param f the text component to decorate
035     * @return an instance of the decorator in order to access the compiled search via {@link #getMatch()}
036     */
037    public static CompileSearchTextDecorator decorate(JTextComponent f) {
038        return new CompileSearchTextDecorator(f);
039    }
040
041    private void setFilter() {
042        try {
043            textComponent.setBackground(UIManager.getColor("TextField.background"));
044            textComponent.setToolTipText(originalToolTipText);
045            filter = SearchCompiler.compile(textComponent.getText());
046        } catch (SearchParseError ex) {
047            textComponent.setBackground(new Color(255, 224, 224));
048            textComponent.setToolTipText(ex.getMessage());
049            filter = SearchCompiler.Always.INSTANCE;
050            Logging.debug(ex);
051        }
052        textComponent.firePropertyChange("filter", 0, 1);
053    }
054
055    /**
056     * Returns the compiled search
057     * @return the compiled search
058     */
059    public SearchCompiler.Match getMatch() {
060        return filter;
061    }
062
063    @Override
064    public void insertUpdate(DocumentEvent e) {
065        setFilter();
066    }
067
068    @Override
069    public void removeUpdate(DocumentEvent e) {
070        setFilter();
071    }
072
073    @Override
074    public void changedUpdate(DocumentEvent e) {
075        setFilter();
076    }
077}