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