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}